django-database-task 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_database_task-0.2.2/django_database_task.egg-info → django_database_task-0.2.3}/PKG-INFO +36 -2
- {django_database_task-0.2.2 → django_database_task-0.2.3}/README.md +35 -1
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/__init__.py +1 -1
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/backends.py +28 -6
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/cloudtasks/auth.py +28 -1
- {django_database_task-0.2.2 → django_database_task-0.2.3/django_database_task.egg-info}/PKG-INFO +36 -2
- {django_database_task-0.2.2 → django_database_task-0.2.3}/pyproject.toml +1 -1
- {django_database_task-0.2.2 → django_database_task-0.2.3}/LICENSE +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/MANIFEST.in +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/admin.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/apps.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/cloudtasks/__init__.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/cloudtasks/backend.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/cloudtasks/detection.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/executor.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/locale/ja/LC_MESSAGES/django.mo +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/locale/ja/LC_MESSAGES/django.po +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/management/__init__.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/management/commands/__init__.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/management/commands/purge_completed_database_tasks.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/management/commands/run_database_tasks.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/migrations/0001_initial.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/migrations/__init__.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/models.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/urls.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/views.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task.egg-info/SOURCES.txt +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task.egg-info/dependency_links.txt +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task.egg-info/requires.txt +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task.egg-info/top_level.txt +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/setup.cfg +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/tests/test_admin.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/tests/test_backend.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/tests/test_commands.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/tests/test_executor.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/tests/test_models.py +0 -0
- {django_database_task-0.2.2 → django_database_task-0.2.3}/tests/test_views.py +0 -0
{django_database_task-0.2.2/django_database_task.egg-info → django_database_task-0.2.3}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-database-task
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: A database-backed task queue backend for Django 6.0's built-in task framework
|
|
5
5
|
Author-email: Shinya Okano <tokibito@gmail.com>
|
|
6
6
|
Maintainer-email: Shinya Okano <tokibito@gmail.com>
|
|
@@ -717,6 +717,40 @@ TASKS = {
|
|
|
717
717
|
|
|
718
718
|
When `OIDC_SERVICE_ACCOUNT_EMAIL` is configured, Cloud Tasks will send OIDC tokens with each request. The backend automatically verifies these tokens on the `/tasks/execute/` and `/tasks/purge/` endpoints.
|
|
719
719
|
|
|
720
|
+
#### Required IAM Roles
|
|
721
|
+
|
|
722
|
+
To use OIDC authentication, the following IAM roles are required:
|
|
723
|
+
|
|
724
|
+
| Role | Description |
|
|
725
|
+
|------|-------------|
|
|
726
|
+
| `roles/cloudtasks.enqueuer` | Required to create tasks in Cloud Tasks queues |
|
|
727
|
+
| `roles/iam.serviceAccountUser` | Required to specify the OIDC service account when creating tasks |
|
|
728
|
+
|
|
729
|
+
**Setup:**
|
|
730
|
+
|
|
731
|
+
1. Create a service account for OIDC token generation:
|
|
732
|
+
```bash
|
|
733
|
+
gcloud iam service-accounts create cloud-tasks-invoker \
|
|
734
|
+
--display-name="Cloud Tasks Invoker"
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
2. Grant the Cloud Tasks Enqueuer role to the service account running your application (e.g., App Engine default service account):
|
|
738
|
+
```bash
|
|
739
|
+
gcloud projects add-iam-policy-binding PROJECT_ID \
|
|
740
|
+
--member="serviceAccount:PROJECT_ID@appspot.gserviceaccount.com" \
|
|
741
|
+
--role="roles/cloudtasks.enqueuer"
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
3. Grant the Service Account User role to allow impersonation of the OIDC service account:
|
|
745
|
+
```bash
|
|
746
|
+
gcloud iam service-accounts add-iam-policy-binding \
|
|
747
|
+
cloud-tasks-invoker@PROJECT_ID.iam.gserviceaccount.com \
|
|
748
|
+
--member="serviceAccount:PROJECT_ID@appspot.gserviceaccount.com" \
|
|
749
|
+
--role="roles/iam.serviceAccountUser"
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
**Note:** The OIDC service account specified in `OIDC_SERVICE_ACCOUNT_EMAIL` does not need any additional roles. It is only used to generate the OIDC token that is included in the HTTP request to your task handler.
|
|
753
|
+
|
|
720
754
|
```python
|
|
721
755
|
# settings.py - Automatic OIDC verification
|
|
722
756
|
TASKS = {
|
|
@@ -724,7 +758,7 @@ TASKS = {
|
|
|
724
758
|
"BACKEND": "django_database_task.cloudtasks.CloudTasksDatabaseBackend",
|
|
725
759
|
"QUEUES": [], # Allow all queue names
|
|
726
760
|
"OPTIONS": {
|
|
727
|
-
"OIDC_SERVICE_ACCOUNT_EMAIL": "
|
|
761
|
+
"OIDC_SERVICE_ACCOUNT_EMAIL": "cloud-tasks-invoker@PROJECT_ID.iam.gserviceaccount.com",
|
|
728
762
|
# OIDC_AUDIENCE is auto-detected from handler URL if not set
|
|
729
763
|
},
|
|
730
764
|
},
|
|
@@ -681,6 +681,40 @@ TASKS = {
|
|
|
681
681
|
|
|
682
682
|
When `OIDC_SERVICE_ACCOUNT_EMAIL` is configured, Cloud Tasks will send OIDC tokens with each request. The backend automatically verifies these tokens on the `/tasks/execute/` and `/tasks/purge/` endpoints.
|
|
683
683
|
|
|
684
|
+
#### Required IAM Roles
|
|
685
|
+
|
|
686
|
+
To use OIDC authentication, the following IAM roles are required:
|
|
687
|
+
|
|
688
|
+
| Role | Description |
|
|
689
|
+
|------|-------------|
|
|
690
|
+
| `roles/cloudtasks.enqueuer` | Required to create tasks in Cloud Tasks queues |
|
|
691
|
+
| `roles/iam.serviceAccountUser` | Required to specify the OIDC service account when creating tasks |
|
|
692
|
+
|
|
693
|
+
**Setup:**
|
|
694
|
+
|
|
695
|
+
1. Create a service account for OIDC token generation:
|
|
696
|
+
```bash
|
|
697
|
+
gcloud iam service-accounts create cloud-tasks-invoker \
|
|
698
|
+
--display-name="Cloud Tasks Invoker"
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
2. Grant the Cloud Tasks Enqueuer role to the service account running your application (e.g., App Engine default service account):
|
|
702
|
+
```bash
|
|
703
|
+
gcloud projects add-iam-policy-binding PROJECT_ID \
|
|
704
|
+
--member="serviceAccount:PROJECT_ID@appspot.gserviceaccount.com" \
|
|
705
|
+
--role="roles/cloudtasks.enqueuer"
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
3. Grant the Service Account User role to allow impersonation of the OIDC service account:
|
|
709
|
+
```bash
|
|
710
|
+
gcloud iam service-accounts add-iam-policy-binding \
|
|
711
|
+
cloud-tasks-invoker@PROJECT_ID.iam.gserviceaccount.com \
|
|
712
|
+
--member="serviceAccount:PROJECT_ID@appspot.gserviceaccount.com" \
|
|
713
|
+
--role="roles/iam.serviceAccountUser"
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
**Note:** The OIDC service account specified in `OIDC_SERVICE_ACCOUNT_EMAIL` does not need any additional roles. It is only used to generate the OIDC token that is included in the HTTP request to your task handler.
|
|
717
|
+
|
|
684
718
|
```python
|
|
685
719
|
# settings.py - Automatic OIDC verification
|
|
686
720
|
TASKS = {
|
|
@@ -688,7 +722,7 @@ TASKS = {
|
|
|
688
722
|
"BACKEND": "django_database_task.cloudtasks.CloudTasksDatabaseBackend",
|
|
689
723
|
"QUEUES": [], # Allow all queue names
|
|
690
724
|
"OPTIONS": {
|
|
691
|
-
"OIDC_SERVICE_ACCOUNT_EMAIL": "
|
|
725
|
+
"OIDC_SERVICE_ACCOUNT_EMAIL": "cloud-tasks-invoker@PROJECT_ID.iam.gserviceaccount.com",
|
|
692
726
|
# OIDC_AUDIENCE is auto-detected from handler URL if not set
|
|
693
727
|
},
|
|
694
728
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import logging
|
|
2
3
|
import traceback
|
|
3
4
|
from importlib import import_module
|
|
4
5
|
from inspect import iscoroutinefunction
|
|
@@ -10,6 +11,8 @@ from django.tasks.signals import task_enqueued, task_finished, task_started
|
|
|
10
11
|
from django.utils import timezone
|
|
11
12
|
from django.utils.json import normalize_json
|
|
12
13
|
|
|
14
|
+
logger = logging.getLogger("django_database_task")
|
|
15
|
+
|
|
13
16
|
|
|
14
17
|
class DatabaseTaskBackend(BaseTaskBackend):
|
|
15
18
|
"""A task backend that persists tasks in the database."""
|
|
@@ -200,6 +203,20 @@ class DatabaseTaskBackend(BaseTaskBackend):
|
|
|
200
203
|
]
|
|
201
204
|
)
|
|
202
205
|
|
|
206
|
+
# Send signal for success
|
|
207
|
+
db_task.refresh_from_db()
|
|
208
|
+
final_result = self._db_task_to_result(db_task, task)
|
|
209
|
+
# Note: Django's task_finished handler logs "NoneType: None" after this
|
|
210
|
+
# due to exc_info=sys.exc_info() being called outside exception context.
|
|
211
|
+
# This is a known Django issue and will be fixed upstream.
|
|
212
|
+
logger.info(
|
|
213
|
+
"Task completed successfully: id=%s path=%s",
|
|
214
|
+
final_result.id,
|
|
215
|
+
db_task.task_path,
|
|
216
|
+
)
|
|
217
|
+
task_finished.send(sender=self.__class__, task_result=final_result)
|
|
218
|
+
return final_result
|
|
219
|
+
|
|
203
220
|
except Exception as e:
|
|
204
221
|
# Failure
|
|
205
222
|
error = TaskError(
|
|
@@ -221,9 +238,14 @@ class DatabaseTaskBackend(BaseTaskBackend):
|
|
|
221
238
|
update_fields=["status", "errors_json", "finished_at", "updated_at"]
|
|
222
239
|
)
|
|
223
240
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
241
|
+
# Send signal for failure (with exception context for Django's logging)
|
|
242
|
+
db_task.refresh_from_db()
|
|
243
|
+
final_result = self._db_task_to_result(db_task, task)
|
|
244
|
+
logger.error(
|
|
245
|
+
"Task failed: id=%s path=%s error=%s",
|
|
246
|
+
final_result.id,
|
|
247
|
+
db_task.task_path,
|
|
248
|
+
error.exception_class_path,
|
|
249
|
+
)
|
|
250
|
+
task_finished.send(sender=self.__class__, task_result=final_result)
|
|
251
|
+
return final_result
|
{django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/cloudtasks/auth.py
RENAMED
|
@@ -5,12 +5,16 @@ Provides authentication handler and decorator for verifying OIDC tokens
|
|
|
5
5
|
sent by Cloud Tasks.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import logging
|
|
9
|
+
import traceback
|
|
8
10
|
from functools import wraps
|
|
9
11
|
|
|
10
12
|
from django.http import JsonResponse
|
|
11
13
|
from google.auth.transport import requests as google_requests
|
|
12
14
|
from google.oauth2 import id_token
|
|
13
15
|
|
|
16
|
+
logger = logging.getLogger("django_database_task.cloudtasks.auth")
|
|
17
|
+
|
|
14
18
|
|
|
15
19
|
def create_oidc_auth_handler(audience):
|
|
16
20
|
"""
|
|
@@ -64,8 +68,31 @@ def create_oidc_auth_handler(audience):
|
|
|
64
68
|
# Attach claims to request for use in view
|
|
65
69
|
request.cloud_tasks_claims = claims
|
|
66
70
|
|
|
71
|
+
# Log successful verification
|
|
72
|
+
service_account = claims.get("email", "unknown")
|
|
73
|
+
logger.info(
|
|
74
|
+
"OIDC token verified successfully: service_account=%s audience=%s",
|
|
75
|
+
service_account,
|
|
76
|
+
audience,
|
|
77
|
+
)
|
|
78
|
+
|
|
67
79
|
except Exception as e:
|
|
68
|
-
|
|
80
|
+
# Log the full exception for debugging
|
|
81
|
+
# Use print as fallback since logging config may not capture this logger
|
|
82
|
+
error_type = type(e).__name__
|
|
83
|
+
error_msg = str(e) if str(e) else "No details available"
|
|
84
|
+
tb = traceback.format_exc()
|
|
85
|
+
full_error = (
|
|
86
|
+
f"OIDC token verification failed: {error_type}: {error_msg}\n{tb}"
|
|
87
|
+
)
|
|
88
|
+
logger.error(full_error)
|
|
89
|
+
# Also print to stderr for environments where logging is not configured
|
|
90
|
+
import sys
|
|
91
|
+
|
|
92
|
+
print(full_error, file=sys.stderr)
|
|
93
|
+
return JsonResponse(
|
|
94
|
+
{"error": f"Invalid token: {error_type}: {error_msg}"}, status=401
|
|
95
|
+
)
|
|
69
96
|
|
|
70
97
|
return None
|
|
71
98
|
|
{django_database_task-0.2.2 → django_database_task-0.2.3/django_database_task.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-database-task
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: A database-backed task queue backend for Django 6.0's built-in task framework
|
|
5
5
|
Author-email: Shinya Okano <tokibito@gmail.com>
|
|
6
6
|
Maintainer-email: Shinya Okano <tokibito@gmail.com>
|
|
@@ -717,6 +717,40 @@ TASKS = {
|
|
|
717
717
|
|
|
718
718
|
When `OIDC_SERVICE_ACCOUNT_EMAIL` is configured, Cloud Tasks will send OIDC tokens with each request. The backend automatically verifies these tokens on the `/tasks/execute/` and `/tasks/purge/` endpoints.
|
|
719
719
|
|
|
720
|
+
#### Required IAM Roles
|
|
721
|
+
|
|
722
|
+
To use OIDC authentication, the following IAM roles are required:
|
|
723
|
+
|
|
724
|
+
| Role | Description |
|
|
725
|
+
|------|-------------|
|
|
726
|
+
| `roles/cloudtasks.enqueuer` | Required to create tasks in Cloud Tasks queues |
|
|
727
|
+
| `roles/iam.serviceAccountUser` | Required to specify the OIDC service account when creating tasks |
|
|
728
|
+
|
|
729
|
+
**Setup:**
|
|
730
|
+
|
|
731
|
+
1. Create a service account for OIDC token generation:
|
|
732
|
+
```bash
|
|
733
|
+
gcloud iam service-accounts create cloud-tasks-invoker \
|
|
734
|
+
--display-name="Cloud Tasks Invoker"
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
2. Grant the Cloud Tasks Enqueuer role to the service account running your application (e.g., App Engine default service account):
|
|
738
|
+
```bash
|
|
739
|
+
gcloud projects add-iam-policy-binding PROJECT_ID \
|
|
740
|
+
--member="serviceAccount:PROJECT_ID@appspot.gserviceaccount.com" \
|
|
741
|
+
--role="roles/cloudtasks.enqueuer"
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
3. Grant the Service Account User role to allow impersonation of the OIDC service account:
|
|
745
|
+
```bash
|
|
746
|
+
gcloud iam service-accounts add-iam-policy-binding \
|
|
747
|
+
cloud-tasks-invoker@PROJECT_ID.iam.gserviceaccount.com \
|
|
748
|
+
--member="serviceAccount:PROJECT_ID@appspot.gserviceaccount.com" \
|
|
749
|
+
--role="roles/iam.serviceAccountUser"
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
**Note:** The OIDC service account specified in `OIDC_SERVICE_ACCOUNT_EMAIL` does not need any additional roles. It is only used to generate the OIDC token that is included in the HTTP request to your task handler.
|
|
753
|
+
|
|
720
754
|
```python
|
|
721
755
|
# settings.py - Automatic OIDC verification
|
|
722
756
|
TASKS = {
|
|
@@ -724,7 +758,7 @@ TASKS = {
|
|
|
724
758
|
"BACKEND": "django_database_task.cloudtasks.CloudTasksDatabaseBackend",
|
|
725
759
|
"QUEUES": [], # Allow all queue names
|
|
726
760
|
"OPTIONS": {
|
|
727
|
-
"OIDC_SERVICE_ACCOUNT_EMAIL": "
|
|
761
|
+
"OIDC_SERVICE_ACCOUNT_EMAIL": "cloud-tasks-invoker@PROJECT_ID.iam.gserviceaccount.com",
|
|
728
762
|
# OIDC_AUDIENCE is auto-detected from handler URL if not set
|
|
729
763
|
},
|
|
730
764
|
},
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task/cloudtasks/backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{django_database_task-0.2.2 → django_database_task-0.2.3}/django_database_task.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|