Skip to content

Commit

Permalink
image detail view with add / remove and delete functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Glatthard committed Aug 12, 2015
1 parent 969d1ea commit 16d1e1e
Show file tree
Hide file tree
Showing 13 changed files with 458 additions and 36 deletions.
2 changes: 2 additions & 0 deletions ipynbsrv/api/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ class ContainerImageSerializer(serializers.ModelSerializer):
Todo: write doc.
"""
friendly_name = serializers.CharField(read_only=True, source='get_friendly_name')
owner = UserSerializer(many=False)
access_groups = FlatCollaborationGroupSerializer(many=True, read_only=True)

class Meta:
model = ContainerImage
Expand Down
2 changes: 2 additions & 0 deletions ipynbsrv/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
# /api/container/images(/)...
url(r'^containers/images/?$', views.ContainerImageList.as_view(), name="images"),
url(r'^containers/images/(?P<pk>[0-9]+)$', views.ContainerImageDetail.as_view(), name="image_detail"),
url(r'^containers/images/(?P<pk>[0-9]+)/add_access_groups$', views.image_add_access_groups, name="image_add_access_groups"),
url(r'^containers/images/(?P<pk>[0-9]+)/remove_access_groups$', views.image_remove_access_groups, name="image_remove_access_groups"),

# /api/container/snapshots(/)...
url(r'^containers/snapshots/?$', views.ContainerSnapshotList.as_view(), name="snapshot"),
Expand Down
134 changes: 118 additions & 16 deletions ipynbsrv/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ def api_root(request, format=None):
}
available_endpoints['containers'] = {
'': 'Get a list of all containers available to your user.',
'images': 'Get a list of all container images available to your user.',
'images': {
'': 'Get a list of all container images available to your user.',
'{id}': {
'add_access_groups': 'Add access_groups to the share.',
'remove_access_groups': 'Remove access_groups from the share.'
}
},
'snapshots': 'Get a list of all container snapshots available to your user.',
'{id}': {
'': 'Get details about a container.',
Expand Down Expand Up @@ -727,6 +733,95 @@ class ContainerImageDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = ContainerImage.objects.all()


@api_view(['POST'])
def image_add_access_groups(request, pk):
"""
Add a list of collaboration groups to the image.
Todo: show params on OPTIONS call.
Todo: permissions
:param pk pk of the collaboration group
"""
required_params = ["access_groups"]
params = validate_request_params(required_params, request)

obj = ContainerImage.objects.filter(id=pk)
if not obj:
return Response({"error": "Image not found!", "data": request.data})
image = obj.first()

# validate permissions
# validate_object_permission(ShareDetailPermissions, request, share)

# validate all the access_groups first before adding them
access_groups = []
for access_group_id in params.get("access_groups"):
obj = CollaborationGroup.objects.filter(id=access_group_id)
if not obj:
return Response(
{"error": "CollaborationGroup not found!", "data": access_group_id},
status=status.HTTP_404_NOT_FOUND
)
access_groups.append(obj.first())

added_groups = []
# add the access groups to the share
for access_group in access_groups:
if image.add_access_group(access_group):
added_groups.append((access_group.id, access_group.name))

return Response({
"detail": "Groups added successfully",
"groups": added_groups,
"count": len(added_groups)
},
status=status.HTTP_200_OK
)


@api_view(['POST'])
def image_remove_access_groups(request, pk):
"""
Remove a list of collaboration groups from the image.
Todo: show params on OPTIONS call.
Todo: permissions
:param pk pk of the collaboration group
"""
required_params = ["access_groups"]
params = validate_request_params(required_params, request)
obj = ContainerImage.objects.filter(id=pk)
if not obj:
return Response({"error": "Image not found!", "data": request.data})
image = obj.first()

# validate permissions
# validate_object_permission(ShareDetailPermissions, request, share)

# validate all the access_groups first before adding them
access_groups = []
for access_group_id in params.get("access_groups"):
obj = CollaborationGroup.objects.filter(id=access_group_id)
if not obj:
return Response(
{"error": "CollaborationGroup not found!", "data": access_group_id},
status=status.HTTP_404_NOT_FOUND
)
access_groups.append(obj.first())

removed_groups = []
# add the access groups to the share
for access_group in access_groups:
if image.remove_access_group(access_group):
removed_groups.append((access_group.id, access_group.name))

return Response({
"detail": "Groups removed successfully",
"groups": removed_groups,
"count": len(removed_groups)
},
status=status.HTTP_200_OK
)


class ContainerSnapshotsList(generics.ListAPIView):
"""
Get a list of all snapshots for a specific container.
Expand Down Expand Up @@ -860,8 +955,6 @@ def share_add_access_groups(request, pk):
"""
required_params = ["access_groups"]
params = validate_request_params(required_params, request)
print("add access groups")
print(params)

obj = Share.objects.filter(id=pk)
if not obj:
Expand All @@ -880,15 +973,21 @@ def share_add_access_groups(request, pk):
{"error": "CollaborationGroup not found!", "data": access_group_id},
status=status.HTTP_404_NOT_FOUND
)
print(obj.first())
access_groups.append(obj.first())

added_groups = []
# add the access groups to the share
for access_group in access_groups:
share.add_access_group(access_group)
if share.add_access_group(access_group):
added_groups.append((access_group.id, access_group.name))

serializer = NestedShareSerializer(share)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response({
"detail": "Groups added successfully",
"groups": added_groups,
"count": len(added_groups)
},
status=status.HTTP_200_OK
)


@api_view(['POST'])
Expand All @@ -899,10 +998,9 @@ def share_remove_access_groups(request, pk):
Todo: permissions
:param pk pk of the collaboration group
"""
print("remove access groups")
required_params = ["access_groups"]
params = validate_request_params(required_params, request)
print(params)

obj = Share.objects.filter(id=pk)
if not obj:
return Response({"error": "Share not found!", "data": request.data})
Expand All @@ -922,15 +1020,19 @@ def share_remove_access_groups(request, pk):
)
access_groups.append(obj.first())

removed_groups = []
# add the access groups to the share
for access_group in access_groups:
share.remove_access_group(access_group)
print("after remove from model")

print("after all")

serializer = NestedShareSerializer(share)
return Response(serializer.data, status=status.HTTP_201_CREATED)
if share.remove_access_group(access_group):
removed_groups.append((access_group.id, access_group.name))

return Response({
"detail": "Groups removed successfully",
"groups": removed_groups,
"count": len(removed_groups)
},
status=status.HTTP_200_OK
)


class TagList(generics.ListCreateAPIView):
Expand Down
21 changes: 19 additions & 2 deletions ipynbsrv/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ class ContainerImage(models.Model):
help_text='A short description of the container image.'
)
description = models.TextField(
blank=True,
blank=True,
null=True,
help_text='Detailed information on how to use this image.'
)
Expand All @@ -799,7 +799,6 @@ class ContainerImage(models.Model):
related_name='images',
help_text='The groups having access to that image.'
)

command = models.CharField(
blank=True,
null=True,
Expand Down Expand Up @@ -828,6 +827,24 @@ class ContainerImage(models.Model):
is_internal = models.BooleanField(default=False)
is_public = models.BooleanField(default=False)

def add_access_group(self, group):
"""
Add access group to image.
"""
if group not in self.access_groups.all():
self.access_groups.add(group)
return True
return False

def remove_access_group(self, group):
"""
Remove access group from image.
"""
if group in self.access_groups.all():
self.access_groups.remove(group)
return True
return False

def get_friendly_name(self):
"""
Return the humen-friendly name of this image.
Expand Down
8 changes: 5 additions & 3 deletions ipynbsrv/web/templates/web/images/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,23 @@ <h1>Images</h1>
<thead>
<tr>
<th width="25%">Name</th>
<th width="55%">Short Description</th>
<th width="40%">Short Description</th>
<th width="15%">Owner</th>
<th width="10%" style="text-align: center">Public</th>
<th width="10%" style="text-align: right">Actions</th>
</tr>
</thead>
<tbody>
{% for img in images %}
<tr>
<td>{{ img.friendly_name }}</td>
<td><a href="{% url 'image_manage' img.id %}">{{ img.friendly_name }}</a></td>
<td>{{ img.short_description }}</td>
<td>{{ img.owner.username }}</td>
<td style="text-align: center">
<input type="checkbox" data-sort="1"{% if img.is_public %} checked{% endif %}{% if img.owner != request.user.id %} disabled{% endif %}>
</td>
<td>
{% if img.owner == request.user.id %}
{% if img.owner.id == request.user.id %}
<form action="{% url 'image_delete' %}" method="POST" class="pull-right" role="form">
{% csrf_token %}
<input type="hidden" name="id" value="{{ img.id }}">
Expand Down
Loading

0 comments on commit 16d1e1e

Please sign in to comment.