Skip to content

Commit 58b7a28

Browse files
committed
Add app versioning
1 parent e0d7e40 commit 58b7a28

File tree

10 files changed

+312
-84
lines changed

10 files changed

+312
-84
lines changed

apps/apis.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from .models import AppVisibility
3030
from .models import TestCase
3131
from .models import TestSet
32-
from .serializers import AppHubSerializer
32+
from .serializers import AppDataSerializer, AppHubSerializer
3333
from .serializers import AppSerializer
3434
from .serializers import AppTemplateSerializer
3535
from .serializers import AppTypeSerializer
@@ -140,6 +140,33 @@ def getShared(self, request):
140140
)
141141
return DRFResponse(serializer.data)
142142

143+
def versions(self, request, uid=None, version=None):
144+
draft = request.query_params.get('draft', False)
145+
146+
if not uid:
147+
return DRFResponse(status=400, data={'message': 'uid is required'})
148+
149+
app = get_object_or_404(
150+
App,
151+
Q(uuid=uuid.UUID(uid), owner=request.user) |
152+
Q(uuid=uuid.UUID(uid), accessible_by__contains=[
153+
request.user.email], visibility=AppVisibility.PRIVATE, is_published=True),
154+
)
155+
156+
if version:
157+
versioned_app_data = AppData.objects.filter(
158+
app_uuid=app.uuid, version=version, is_draft=draft
159+
).first()
160+
if versioned_app_data:
161+
return DRFResponse(AppDataSerializer(versioned_app_data, context={'hide_details': False}).data)
162+
else:
163+
return DRFResponse(status=404, data={'message': 'Version not found'})
164+
else:
165+
queryset = AppData.objects.all().filter(
166+
app_uuid=app.uuid).order_by('-created_at')
167+
serializer = AppDataSerializer(queryset, many=True)
168+
return DRFResponse(serializer.data)
169+
143170
@xframe_options_exempt
144171
def getByPublishedUUID(self, request, published_uuid):
145172
app = get_object_or_404(App, published_uuid=published_uuid)
@@ -156,7 +183,7 @@ def getByPublishedUUID(self, request, published_uuid):
156183
(
157184
request.user.is_authenticated and ((app.visibility == AppVisibility.ORGANIZATION and Profile.objects.get(user=app.owner).organization == Profile.objects.get(user=request.user).organization) or
158185
(app.visibility == AppVisibility.PRIVATE and request.user.email in app.accessible_by))
159-
):
186+
):
160187
serializer = AppSerializer(
161188
instance=app, request_user=request.user,
162189
)
@@ -388,8 +415,11 @@ def patch(self, request, uid):
388415
versioned_app_data.is_draft = draft
389416
versioned_app_data.save()
390417
else:
418+
# Find the total number of published versions
419+
published_versions = AppData.objects.filter(
420+
app_uuid=app.uuid, is_draft=False).count()
391421
AppData.objects.create(
392-
app_uuid=app.uuid, data=app_data, comment=comment, is_draft=draft
422+
app_uuid=app.uuid, data=app_data, comment=comment, is_draft=draft, version=published_versions,
393423
)
394424

395425
app.last_modified_by = request.user
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.2.1 on 2023-09-06 22:34
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('apps', '0004_app_data_from_app'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='appdata',
15+
name='version',
16+
field=models.IntegerField(default=0, help_text='Version of the app'),
17+
),
18+
]

apps/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ class AppData(models.Model):
248248
app_uuid = models.UUIDField(
249249
default=None, help_text='UUID of the app', null=True, blank=True,
250250
)
251+
version = models.IntegerField(
252+
default=0, help_text='Version of the app',
253+
)
251254
data = models.JSONField(
252255
default=dict, blank=True,
253256
help_text='Data for this endpoint',
@@ -268,6 +271,9 @@ class AppData(models.Model):
268271
auto_now=True, help_text='Time at which the app instance was last updated',
269272
)
270273

274+
def __str__(self) -> str:
275+
return f'{self.app_uuid}_{"draft" if self.is_draft else "published"}_v{self.version}'
276+
271277

272278
class AppHub(models.Model):
273279
app = models.ForeignKey(

apps/serializers.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,23 @@ class Meta:
313313
]
314314

315315

316+
class AppDataSerializer(serializers.ModelSerializer):
317+
318+
data = serializers.SerializerMethodField()
319+
320+
def get_data(self, obj):
321+
hide_details = self.context.get('hide_details', True)
322+
if hide_details:
323+
return None
324+
325+
return obj.data
326+
327+
class Meta:
328+
model = AppData
329+
fields = ['version', 'app_uuid', 'data',
330+
'created_at', 'last_updated_at', 'is_draft', 'comment']
331+
332+
316333
class AppHubSerializer(serializers.ModelSerializer):
317334
published_uuid = serializers.SerializerMethodField()
318335
name = serializers.SerializerMethodField()

apps/urls.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,14 @@
2929
path('api/apps/shared', apis.AppViewSet.as_view({'get': 'getShared'})),
3030
path(
3131
'api/apps/<str:uid>',
32-
apis.AppViewSet.as_view({'get': 'get', 'patch': 'patch', 'delete': 'delete'}),
32+
apis.AppViewSet.as_view(
33+
{'get': 'get', 'patch': 'patch', 'delete': 'delete'}),
3334
),
3435
path('api/apps/<str:uid>/run', apis.AppViewSet.as_view({'post': 'run'})),
36+
path('api/apps/<str:uid>/versions',
37+
apis.AppViewSet.as_view({'get': 'versions'})),
38+
path('api/apps/<str:uid>/versions/<str:version>',
39+
apis.AppViewSet.as_view({'get': 'versions'})),
3540
path(
3641
'api/apps/<str:uid>/discord/run',
3742
apis.AppViewSet.as_view({'post': 'run_discord'}),

0 commit comments

Comments
 (0)