Skip to content

Commit

Permalink
Fix(Workspaces): ensure the presence of a token / server hash in memb…
Browse files Browse the repository at this point in the history
…erships (#552)

* Fix(Workspaces): ensure the presence of a token (and a server hash) for each membership

* Fix(Workspaces): ensure the presence of a token (and a server hash) for each membership

* Fix(Workspaces): ensure the presence of a token (and a server hash) for each membership
  • Loading branch information
pvanliefland authored Sep 25, 2023
1 parent 294fc44 commit 1f1c4da
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
1 change: 1 addition & 0 deletions hexa/workspaces/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class WorkspaceMembershipAdmin(admin.ModelAdmin):
"created_at",
"updated_at",
)
readonly_fields = ("notebooks_server_hash",)


class ConnectionFieldInline(admin.StackedInline):
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
),
),
]
21 changes: 15 additions & 6 deletions hexa/workspaces/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
11 changes: 10 additions & 1 deletion hexa/workspaces/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand All @@ -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(
Expand Down

0 comments on commit 1f1c4da

Please sign in to comment.