Skip to content

Commit

Permalink
Merge pull request #673 from bounswe/semantic-tag
Browse files Browse the repository at this point in the history
Semantic tag post api and remove workspace tag put api
  • Loading branch information
Simurgan authored Dec 23, 2023
2 parents d8d210d + 8801784 commit 9eecd3a
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 1 deletion.
163 changes: 163 additions & 0 deletions project/backend/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,169 @@

# Create your tests here for each class or API call.

class SemanticTagAPITestCase(TestCase):
def setUp(self):
self.client = APIClient()
self.url_add = reverse("add_semantic_tag")
self.url_remove = reverse("remove_workspace_tag")

self.wid = "Q486598"
self.label1 = "Test Semantic Tag Label 1"
self.label2 = "Test Semantic Tag Label 2"
self.label3 = "Test Semantic Tag Label 3"
self.user_for_contributor = User.objects.create_user(id=2, email= '[email protected]', username='[email protected]', first_name='Contributor User 2', last_name='Test2')
self.user_for_contributor2 = User.objects.create_user(id=3, email= '[email protected]', username='[email protected]', first_name='Contributor User 3', last_name='Test3')
self.contributor = Contributor.objects.create(user=self.user_for_contributor, bio="I am the contributor")
self.contributor2 = Contributor.objects.create(user=self.user_for_contributor2, bio="I am the second contributor")

self.contributor_token = Token.objects.create(user=self.user_for_contributor)
self.contributor2_token = Token.objects.create(user=self.user_for_contributor2)

self.workspace = Workspace.objects.create()
self.contributor.workspaces.add(self.workspace)

def tearDown(self):
Workspace.objects.all().delete()
Contributor.objects.all().delete()
BasicUser.objects.all().delete()
User.objects.all().delete()
SemanticTag.objects.all().delete()
print("All tests for the Semantic Tag API are completed!")

def test_add_semantic_tag(self):
data_complete = {
"wid": self.wid,
"label": self.label2,
"workspace_id": self.workspace.workspace_id
}
response = self.client.post(self.url_add, data_complete, format="json")
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
self.assertEqual(response.data["detail"], "Authentication credentials were not provided.")

self.client.credentials(HTTP_AUTHORIZATION=f"Token {Token.objects.get(user=self.user_for_contributor).key[0:-1]}")
response = self.client.post(self.url_add, data_complete, format="json")
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
self.assertEqual(response.data["detail"], "Invalid token.")

self.client.credentials(HTTP_AUTHORIZATION=f"Token {Token.objects.get(user=self.user_for_contributor2).key}")
response = self.client.post(self.url_add, data_complete, format="json")
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data["detail"], "You do not have permission to perform this action.")

self.client.credentials(HTTP_AUTHORIZATION=f"Token {Token.objects.get(user=self.user_for_contributor).key}")

data_missing_wid = {
"label": self.label1,
"workspace_id": self.workspace.workspace_id
}

response = self.client.post(self.url_add, data_missing_wid, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["wid"][0], "This field is required.")

data_missing_label = {
"wid": self.wid,
"workspace_id": self.workspace.workspace_id
}

response = self.client.post(self.url_add, data_missing_label, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["label"][0], "This field is required.")

data_missing_workspace_id = {
"wid": self.wid,
"label": self.label1
}

response = self.client.post(self.url_add, data_missing_workspace_id, format="json")
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
tags = SemanticTag.objects.filter(wid=self.wid, label=self.label1)
self.assertEqual(tags.count(), 1)
self.assertEqual(tags[0].wid, self.wid)
self.assertEqual(tags[0].wid, response.data["wid"])
self.assertEqual(tags[0].label, self.label1)
self.assertEqual(tags[0].label, response.data["label"])

data_complete = {
"wid": self.wid,
"label": self.label2,
"workspace_id": str(self.workspace.workspace_id)
}

SemanticTag.objects.all().delete()

response = self.client.post(self.url_add, data_complete, format="json")
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
tags = SemanticTag.objects.filter(wid=self.wid, label=self.label2)
self.assertEqual(tags.count(), 1)
self.assertEqual(tags[0].wid, self.wid)
self.assertEqual(tags[0].wid, response.data["wid"])
self.assertEqual(tags[0].label, self.label2)
self.assertEqual(tags[0].label, response.data["label"])

tags = self.workspace.semantic_tags.all()
self.assertEqual(tags.count(), 1)
tag = tags[0]
self.assertEqual(tag.wid, self.wid)
self.assertEqual(tag.wid, response.data["wid"])
self.assertEqual(tag.label, self.label2)
self.assertEqual(tag.label, response.data["label"])

def test_remove_workspace_tag(self):
tag = SemanticTag.objects.create(wid=self.wid, label=self.label3)
self.workspace.semantic_tags.add(tag)

data_complete = {
"workspace_id": self.workspace.workspace_id,
"tag_id": tag.id
}
response = self.client.put(self.url_remove, data_complete, format="json")
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
content = json.loads(response.content)
self.assertEqual(content["message"], "You don't have permission to do this!")

self.client.credentials(HTTP_AUTHORIZATION=f"Token {Token.objects.get(user=self.user_for_contributor).key[0:-1]}")
response = self.client.put(self.url_remove, data_complete, format="json")
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
content = json.loads(response.content)
self.assertEqual(content["detail"], "Invalid token.")

self.client.credentials(HTTP_AUTHORIZATION=f"Token {Token.objects.get(user=self.user_for_contributor2).key}")
response = self.client.put(self.url_remove, data_complete, format="json")
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
content = json.loads(response.content)
self.assertEqual(content["message"], "You don't have permission to do this!")

self.client.credentials(HTTP_AUTHORIZATION=f"Token {Token.objects.get(user=self.user_for_contributor).key}")
data_missing_workspace_id = {
"tag_id": tag.id
}
response = self.client.put(self.url_remove, data_missing_workspace_id, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
content = json.loads(response.content)
self.assertEqual(content["message"], "workspace_id field can not be empty")

data_missing_tag_id = {
"workspace_id": self.workspace.workspace_id
}
response = self.client.put(self.url_remove, data_missing_tag_id, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
content = json.loads(response.content)
self.assertEqual(content["message"], "tag_id field can not be empty")

data_complete = {
"workspace_id": self.workspace.workspace_id,
"tag_id": tag.id
}
response = self.client.put(self.url_remove, data_complete, format="json")
self.assertEqual(response.status_code, status.HTTP_200_OK)
content = json.loads(response.content)
self.assertEqual(content["message"], "Tag is successfully removed from workspace.")

tags = self.workspace.semantic_tags.filter(wid=self.wid, label=self.label3)
self.assertEqual(tags.count(), 0)


class WorkspacePOSTAPITestCase(TestCase):
def setUp(self):
self.client = APIClient()
Expand Down
3 changes: 3 additions & 0 deletions project/backend/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,7 @@
path('promote_contributor/', promote_contributor, name='promote_contributor'),
path('demote_reviewer/', demote_reviewer, name='demote_reviewer'),
path('add_user_semantic_tag/', AddUserSemanticTag.as_view(), name='add_user_semantic_tag'),
path('add_semantic_tag/', SemanticTagAPIView.as_view(), name='add_semantic_tag'),
path('remove_workspace_tag/', remove_workspace_tag, name='remove_workspace_tag'),

]
47 changes: 47 additions & 0 deletions project/backend/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,54 @@ def post(self, request):
serializer.errors, status=400
)

class SemanticTagAPIView(APIView):
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated, IsContributorAndWorkspace)

def post(self, request):
serializer = SemanticTagSerializer(data=request.data, context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(
serializer.errors, status=400
)

def is_workspace_contributor(request):
workspace_id = request.data.get('workspace_id')
if not request.user.is_authenticated:
return False
if not Contributor.objects.filter(pk=request.user.basicuser.pk).exists():
return False
if workspace_id is not None:
return request.user.basicuser.contributor.workspaces.filter(workspace_id=workspace_id).exists()
return True

@api_view(['PUT'])
def remove_workspace_tag(request):
workspace_id = request.data.get("workspace_id")
tag_id = request.data.get("tag_id")

if workspace_id == None or workspace_id == '':
return JsonResponse({'message': 'workspace_id field can not be empty'}, status=400)
try:
workspace_id = int(workspace_id)
except:
return JsonResponse({'message': 'workspace_id field has to be an integer'}, status=400)

if tag_id == None or tag_id == '':
return JsonResponse({'message': 'tag_id field can not be empty'}, status=400)
try:
tag_id = int(tag_id)
except:
return JsonResponse({'message': 'tag_id field has to be an integer'}, status=400)

if is_workspace_contributor(request):
workspace = Workspace.objects.get(workspace_id=workspace_id)
workspace.semantic_tags.remove(tag_id)
return JsonResponse({'message': 'Tag is successfully removed from workspace.'}, status=200)
else:
return JsonResponse({'message': "You don't have permission to do this!"}, status=403)

def search(request):
res = BasicUserDetailAPI.as_view()(request)
Expand Down
2 changes: 1 addition & 1 deletion project/backend/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class SemanticTag(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
wid = models.CharField(max_length=20)
label = models.CharField(max_length=30, unique=True)
label = models.CharField(max_length=30)

@property
def nodes(self):
Expand Down
20 changes: 20 additions & 0 deletions project/backend/database/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,26 @@ def create(self, validated_data):

return workspace

class SemanticTagSerializer(serializers.ModelSerializer):
wid = serializers.CharField(required=True)
label = serializers.CharField(required=True)

class Meta:
model = SemanticTag
fields = "__all__"

def create(self, validated_data):
wid = validated_data.get('wid', None)
label = validated_data.get('label', None)
workspace_id = self.context['request'].data.get('workspace_id', None)

tag = SemanticTag.objects.create(wid=wid, label=label)

if workspace_id is not None:
workspace = Workspace.objects.get(workspace_id=workspace_id)
workspace.semantic_tags.add(tag)

return tag

# Serializer to change password
class ChangePasswordSerializer(serializers.ModelSerializer):
Expand Down

0 comments on commit 9eecd3a

Please sign in to comment.