Skip to content

Commit

Permalink
Merge pull request #1973 from kobotoolbox/issue-1894
Browse files Browse the repository at this point in the history
Feature: endpoint for hash of all assets
  • Loading branch information
pmusaraj authored Sep 6, 2018
2 parents 961f246 + 5c75714 commit 65c5107
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 1 deletion.
24 changes: 24 additions & 0 deletions kpi/tests/test_api_assets.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-

import copy
from hashlib import md5
import json
import requests
import StringIO
Expand Down Expand Up @@ -81,6 +82,29 @@ def test_asset_list_matches_detail(self):
self.assertIsNotNone(list_result_detail)
self.assertDictEqual(expected_list_data, dict(list_result_detail))

def test_assets_hash(self):
another_user = User.objects.get(username="anotheruser")
user_asset = Asset.objects.first()
user_asset.save()
user_asset.assign_perm(another_user, "view_asset")

self.client.logout()
self.client.login(username="anotheruser", password="anotheruser")
creation_response = self.test_create_asset()

another_user_asset = another_user.assets.last()
another_user_asset.save()

versions_ids = [
user_asset.version_id,
another_user_asset.version_id
]
versions_ids.sort()
expected_hash = md5("".join(versions_ids)).hexdigest()
hash_url = reverse("asset-hash-list")
hash_response = self.client.get(hash_url)
self.assertEqual(hash_response.data.get("hash"), expected_hash)


class AssetVersionApiTests(APITestCase):
fixtures = ['test_data']
Expand Down
44 changes: 43 additions & 1 deletion kpi/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from distutils.util import strtobool
from itertools import chain
import copy
from hashlib import md5
import json
import base64
import datetime
Expand Down Expand Up @@ -30,7 +31,7 @@
)
from rest_framework.decorators import api_view
from rest_framework.decorators import renderer_classes
from rest_framework.decorators import detail_route
from rest_framework.decorators import detail_route, list_route
from rest_framework.decorators import authentication_classes
from rest_framework.parsers import MultiPartParser
from rest_framework.response import Response
Expand Down Expand Up @@ -755,6 +756,17 @@ class AssetViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
>
> curl -X GET https://[kpi-url]/assets/
Get an hash of all `version_id`s of assets.
Useful to detect any changes in assets with only one call to `API`
<pre class="prettyprint">
<b>GET</b> /assets/hash/
</pre>
> Example
>
> curl -X GET https://[kpi-url]/assets/hash/
## CRUD
* `uid` - is the unique identifier of a specific asset
Expand Down Expand Up @@ -1000,6 +1012,36 @@ def create(self, request, *args, **kwargs):
return Response(serializer.data, status=status.HTTP_201_CREATED,
headers=headers)

@list_route(methods=["GET"], renderer_classes=[renderers.JSONRenderer])
def hash(self, request):
"""
Creates an hash of `version_id` of all accessible assets by the user.
Useful to detect changes between each request.
:param request:
:return: JSON
"""
user = self.request.user
if user.is_anonymous():
raise exceptions.NotAuthenticated()
else:
accessible_assets = get_objects_for_user(
user, "view_asset", Asset).filter(asset_type=ASSET_TYPE_SURVEY)\
.order_by("uid")

assets_version_ids = [asset.version_id for asset in accessible_assets if asset.version_id is not None]
# Sort alphabetically
assets_version_ids.sort()

if len(assets_version_ids) > 0:
hash = md5("".join(assets_version_ids)).hexdigest()
else:
hash = ""

return Response({
"hash": hash
})

@detail_route(renderer_classes=[renderers.JSONRenderer])
def content(self, request, uid):
asset = self.get_object()
Expand Down

0 comments on commit 65c5107

Please sign in to comment.