diff --git a/hexa/workspaces/admin.py b/hexa/workspaces/admin.py index b4ff35644..fc482e85f 100644 --- a/hexa/workspaces/admin.py +++ b/hexa/workspaces/admin.py @@ -28,6 +28,7 @@ class WorkspaceMembershipAdmin(admin.ModelAdmin): "created_at", "updated_at", ) + readonly_fields = ("notebooks_server_hash",) class ConnectionFieldInline(admin.StackedInline): diff --git a/hexa/workspaces/migrations/0037_alter_workspacemembership_access_token_and_more.py b/hexa/workspaces/migrations/0037_alter_workspacemembership_access_token_and_more.py new file mode 100644 index 000000000..e753aaa71 --- /dev/null +++ b/hexa/workspaces/migrations/0037_alter_workspacemembership_access_token_and_more.py @@ -0,0 +1,46 @@ +# Generated by Django 4.1.7 on 2023-09-25 07:54 + +from django.db import migrations, models + + +def generate_tokens(apps, schema_editor): + WorkspaceMembership = apps.get_model("workspaces", "WorkspaceMembership") + + # Filter the instances without access_token + memberships_without_token = WorkspaceMembership.objects.filter( + models.Q(access_token__isnull=True) | models.Q(access_token="") + ) + + for membership in memberships_without_token: + membership.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ("workspaces", "0036_service_account_key_migration"), + ] + + operations = [ + migrations.RunPython(generate_tokens, reverse_code=migrations.RunPython.noop), + migrations.AlterField( + model_name="workspacemembership", + name="access_token", + field=models.TextField( + blank=True, + help_text="Access token that can be used to interact with the OpenHexa API (will be generated automatically, set to empty to regenerate a new token)", + max_length=50, + unique=True, + ), + ), + migrations.AlterField( + model_name="workspacemembership", + name="notebooks_server_hash", + field=models.TextField( + blank=True, + editable=False, + help_text="Can be used to identify a notebook server for a given user and workspace (will be generated automatically)", + unique=True, + ), + ), + ] diff --git a/hexa/workspaces/models.py b/hexa/workspaces/models.py index 6294bf883..b91d7a37f 100644 --- a/hexa/workspaces/models.py +++ b/hexa/workspaces/models.py @@ -254,22 +254,31 @@ class Meta: on_delete=models.CASCADE, ) role = models.CharField(choices=WorkspaceMembershipRole.choices, max_length=50) - notebooks_server_hash = models.TextField(unique=True, blank=True) - access_token = models.TextField(max_length=50, null=True, blank=True, unique=True) + notebooks_server_hash = models.TextField( + blank=True, + unique=True, + help_text="Can be used to identify a notebook server for a given user and workspace (will be generated automatically)", + editable=False, + ) + access_token = models.TextField( + max_length=50, + blank=True, + unique=True, + help_text="Access token that can be used to interact with the OpenHexa API (will be generated automatically, set to empty to regenerate a new token)", + ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) objects = WorkspaceMembershipManager.from_queryset(WorkspaceMembershipQuerySet)() - def generate_access_token(self): - self.access_token = uuid.uuid4() - self.save() - def save(self, *args, **kwargs): if self.notebooks_server_hash == "": self.notebooks_server_hash = hashlib.blake2s( f"{self.workspace_id}_{self.user_id}".encode("utf-8"), digest_size=16 ).hexdigest() + if self.access_token == "": + self.access_token = uuid.uuid4() + super().save(*args, **kwargs) def update_if_has_perm(self, *, principal: User, role: WorkspaceMembershipRole): diff --git a/hexa/workspaces/tests/test_views.py b/hexa/workspaces/tests/test_views.py index 71d6f8a20..050942c5e 100644 --- a/hexa/workspaces/tests/test_views.py +++ b/hexa/workspaces/tests/test_views.py @@ -46,7 +46,11 @@ def setUpTestData(cls): countries=[{"code": "AL"}], ) - cls.WORKSPACE_MEMBERSHIP = WorkspaceMembership.objects.create( + cls.WORKSPACE_MEMBERSHIP_JULIA = WorkspaceMembership.objects.get( + workspace=cls.WORKSPACE, user=cls.USER_JULIA + ) + + cls.WORKSPACE_MEMBERSHIP_REBECCA = WorkspaceMembership.objects.create( user=cls.USER_REBECCA, workspace=cls.WORKSPACE, role=WorkspaceMembershipRole.VIEWER, @@ -125,6 +129,8 @@ def test_workspace_credentials_200( db_credentials = get_db_server_credentials() + self.maxDiff = None + response_data = response.json() self.assertEqual(response.status_code, 200) self.assertEqual( @@ -145,6 +151,9 @@ def test_workspace_credentials_200( "WORKSPACE_DATABASE_PASSWORD": self.WORKSPACE.db_password, "WORKSPACE_DATABASE_URL": self.WORKSPACE.db_url, "GCS_TOKEN": "gcs-token", + "HEXA_TOKEN": Signer().sign_object( + self.WORKSPACE_MEMBERSHIP_JULIA.access_token + ), }, ) self.assertEqual(