Commit 7940b1d8 authored by Michal Čihař's avatar Michal Čihař

Add read only repository status API

Signed-off-by: default avatarMichal Čihař <michal@cihar.com>
parent ce91f9e6
......@@ -47,6 +47,10 @@ Projects
Returns information about project.
.. http:get:: /api/projects/(string:project)/repository/
Returns information about VCS repository status.
Components
++++++++++
......@@ -64,6 +68,10 @@ Components
:query lock: Boolean whether to lock or not.
.. http:get:: /api/components/(string:project)/(string:component)/repository/
Returns information about VCS repository status.
Translations
++++++++++++
......@@ -90,6 +98,10 @@ Translations
-H "Authorization: Token TOKEN" \
http://example.com/api/translations/hello/android/cs/file/
.. http:get:: /api/translations/(string:project)/(string:component)/(string:language)/repository/
Returns information about VCS repository status.
.. _hooks:
Notification hooks
......
......@@ -54,6 +54,15 @@ class APIBaseTest(APITestCase, RepoTestMixin):
HTTP_AUTHORIZATION='Token ' + user.auth_token.key
)
def do_request(self, name, kwargs, data=None, code=200, superuser=False):
self.authenticate(superuser)
response = self.client.get(
reverse(name, kwargs=kwargs)
)
self.assertEqual(response.status_code, code)
if data is not None:
self.assertEqual(response.data, data)
class ProjectAPITest(APIBaseTest):
def test_list_projects(self):
......@@ -69,6 +78,25 @@ class ProjectAPITest(APIBaseTest):
)
self.assertEqual(response.data['slug'], 'test')
def test_repo_status_denied(self):
self.do_request(
'api:project-repository',
self.project_kwargs,
code=403
)
def test_repo_status(self):
self.do_request(
'api:project-repository',
self.project_kwargs,
superuser=True,
data={
'needs_push': False,
'needs_merge': False,
'needs_commit': False
}
)
class ComponentAPITest(APIBaseTest):
def test_list_components(self):
......@@ -122,6 +150,25 @@ class ComponentAPITest(APIBaseTest):
response = self.client.post(url, {'lock': False})
self.assertEqual(response.data, {'locked': False})
def test_repo_status_denied(self):
self.do_request(
'api:component-repository',
self.component_kwargs,
code=403
)
def test_repo_status(self):
self.do_request(
'api:component-repository',
self.component_kwargs,
superuser=True,
data={
'needs_push': False,
'needs_merge': False,
'needs_commit': False
}
)
class LanguageAPITest(APIBaseTest):
def test_list_languages(self):
......@@ -203,3 +250,22 @@ class TranslationAPITest(APIBaseTest):
response.data,
{'count': 5, 'result': True}
)
def test_repo_status_denied(self):
self.do_request(
'api:translation-repository',
self.translation_kwargs,
code=403
)
def test_repo_status(self):
self.do_request(
'api:translation-repository',
self.translation_kwargs,
superuser=True,
data={
'needs_push': False,
'needs_merge': False,
'needs_commit': False
}
)
......@@ -33,7 +33,7 @@ from weblate.api.serializers import (
from weblate.trans.exporters import EXPORTERS
from weblate.trans.models import Project, SubProject, Translation
from weblate.trans.permissions import (
can_upload_translation, can_lock_subproject,
can_upload_translation, can_lock_subproject, can_see_repository_status,
)
from weblate.lang.models import Language
from weblate.trans.views.helper import download_translation_file
......@@ -57,7 +57,7 @@ class MultipleFieldMixin(object):
return get_object_or_404(queryset, **lookup)
class FileExportViewSet(viewsets.ReadOnlyModelViewSet):
class WeblateViewSet(viewsets.ReadOnlyModelViewSet):
"""
Allows to skip content negotiation for certain requests.
"""
......@@ -71,12 +71,34 @@ class FileExportViewSet(viewsets.ReadOnlyModelViewSet):
renderers = self.get_renderers()
return (renderers[0], renderers[0].media_type)
raise Http404('Not supported exporter')
return super(FileExportViewSet, self).perform_content_negotiation(
return super(WeblateViewSet, self).perform_content_negotiation(
request, force
)
@detail_route(methods=['get', 'post'])
def repository(self, request, **kwargs):
obj = self.get_object()
if hasattr(obj, 'subproject'):
project = obj.subproject.project
elif hasattr(obj, 'project'):
project = obj.project
else:
project = obj
if not can_see_repository_status(request.user, project):
raise PermissionDenied()
return Response(
data={
'needs_commit': obj.repo_needs_commit(),
'needs_merge': obj.repo_needs_merge(),
'needs_push': obj.repo_needs_push(),
}
)
class ProjectViewSet(viewsets.ReadOnlyModelViewSet):
class ProjectViewSet(WeblateViewSet):
"""Translation projects API.
"""
queryset = Project.objects.none()
......@@ -89,7 +111,7 @@ class ProjectViewSet(viewsets.ReadOnlyModelViewSet):
)
class ComponentViewSet(MultipleFieldMixin, viewsets.ReadOnlyModelViewSet):
class ComponentViewSet(MultipleFieldMixin, WeblateViewSet):
"""Translation components API.
"""
queryset = SubProject.objects.none()
......@@ -128,7 +150,7 @@ class ComponentViewSet(MultipleFieldMixin, viewsets.ReadOnlyModelViewSet):
return Response(data=LockSerializer(obj).data)
class TranslationViewSet(MultipleFieldMixin, FileExportViewSet):
class TranslationViewSet(MultipleFieldMixin, WeblateViewSet):
"""Translation components API.
"""
queryset = Translation.objects.none()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment