From 4095908db3ab5b1fe724b81530054e0946aa9411 Mon Sep 17 00:00:00 2001
From: Erwan Rouchet <rouchet@teklia.com>
Date: Tue, 7 Mar 2023 16:45:40 +0100
Subject: [PATCH] Add Task.token

---
 arkindex/documents/fixtures/data.json         |  1 +
 arkindex/ponos/migrations/0037_task_token.py  | 39 +++++++++++++++++++
 .../migrations/0038_task_token_unique.py      | 24 ++++++++++++
 arkindex/ponos/models.py                      | 17 ++++++++
 4 files changed, 81 insertions(+)
 create mode 100644 arkindex/ponos/migrations/0037_task_token.py
 create mode 100644 arkindex/ponos/migrations/0038_task_token_unique.py

diff --git a/arkindex/documents/fixtures/data.json b/arkindex/documents/fixtures/data.json
index afec6b200f..1f63c8fe43 100644
--- a/arkindex/documents/fixtures/data.json
+++ b/arkindex/documents/fixtures/data.json
@@ -3777,6 +3777,7 @@
         "updated": "2020-02-02T01:23:45.678Z",
         "expiry": "2050-03-03T01:23:45.678Z",
         "extra_files": "{}",
+        "token": "MjViMzE5NDQtNzc2YS00YThjLWE1YWUtY2RhYTY2ZmE0OTIzCg==",
         "parents": []
     }
 },
diff --git a/arkindex/ponos/migrations/0037_task_token.py b/arkindex/ponos/migrations/0037_task_token.py
new file mode 100644
index 0000000000..6eb06f62fe
--- /dev/null
+++ b/arkindex/ponos/migrations/0037_task_token.py
@@ -0,0 +1,39 @@
+# Generated by Django 4.1.7 on 2023-03-07 15:19
+
+from django.db import migrations, models
+
+from arkindex.ponos.models import task_token_default
+
+
+def add_task_tokens(apps, schema_editor):
+    Task = apps.get_model('ponos', 'Task')
+    to_update = []
+    for task in Task.objects.filter(token=None).only('id').iterator():
+        task.token = task_token_default()
+        to_update.append(task)
+    Task.objects.bulk_update(to_update, ['token'], batch_size=100)
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('ponos', '0036_hstore_task_env_and_extra_files'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='task',
+            name='token',
+            field=models.CharField(
+                default=task_token_default,
+                max_length=52,
+                # Make the field temporarily nullable and not unique, so that we can
+                # fill the tokens on existing tasks before adding the constraints.
+                null=True,
+            ),
+        ),
+        migrations.RunPython(
+            add_task_tokens,
+            reverse_code=migrations.RunPython.noop,
+        ),
+    ]
diff --git a/arkindex/ponos/migrations/0038_task_token_unique.py b/arkindex/ponos/migrations/0038_task_token_unique.py
new file mode 100644
index 0000000000..5de95c85ee
--- /dev/null
+++ b/arkindex/ponos/migrations/0038_task_token_unique.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.1.7 on 2023-03-07 15:25
+
+from django.db import migrations, models
+
+from arkindex.ponos.models import task_token_default
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('ponos', '0037_task_token'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='task',
+            name='token',
+            field=models.CharField(
+                default=task_token_default,
+                max_length=52,
+                unique=True,
+            ),
+        ),
+    ]
diff --git a/arkindex/ponos/models.py b/arkindex/ponos/models.py
index f6a9cd2d62..8ede5e8e42 100644
--- a/arkindex/ponos/models.py
+++ b/arkindex/ponos/models.py
@@ -1,3 +1,4 @@
+import base64
 import logging
 import os.path
 import random
@@ -605,6 +606,15 @@ def expiry_default():
     return timezone.now() + timedelta(days=30)
 
 
+def task_token_default():
+    """
+    Default value for Task.token.
+
+    :rtype: str
+    """
+    return base64.encodebytes(uuid.uuid4().bytes).strip()
+
+
 class Task(models.Model):
     """
     A task created from a workflow's recipe.
@@ -670,6 +680,13 @@ class Task(models.Model):
     # Remote files required to start the container
     extra_files = HStoreField(default=dict)
 
+    token = models.CharField(
+        default=task_token_default,
+        # The token generation always returns 52 characters
+        max_length=52,
+        unique=True,
+    )
+
     objects = TaskManager()
 
     class Meta:
-- 
GitLab