=== modified file 'dashboard_app/extension.py'
@@ -1,4 +1,23 @@
+# Copyright (C) 2010 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of Launch Control.
+#
+# Launch Control is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License version 3
+# as published by the Free Software Foundation
+#
+# Launch Control is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with Launch Control. If not, see <http://www.gnu.org/licenses/>.
+
import os
+
from lava_server.extension import LavaServerExtension
@@ -22,9 +41,14 @@
@property
def version(self):
+ from dashboard_app import __version__
import versiontools
- import dashboard_app
- return versiontools.format_version(dashboard_app.__version__)
+ return versiontools.format_version(__version__)
+
+ @property
+ def api_class(self):
+ from dashboard_app.xmlrpc import DashboardAPI
+ return DashboardAPI
def contribute_to_settings(self, settings_module):
super(DashboardExtension, self).contribute_to_settings(settings_module)
@@ -55,4 +79,3 @@
# properly, having permissions to login, permissions to view proper data)
settings_module['DATABASES']['dataview'] = dict(settings_module['DATABASES']['default'])
settings_module['DATABASES']['dataview']['USER'] += "_dataview"
-
=== modified file 'dashboard_app/tests/other/dashboard_api.py'
@@ -31,38 +31,6 @@
from dashboard_app.xmlrpc import errors
-class DashboardAPITests(DashboardXMLRPCViewsTestCase):
-
- def test_xml_rpc_help_returns_200(self):
- response = self.client.get(self.endpoint_path)
- self.assertEqual(response.status_code, 200)
-
- def test_help_page_lists_all_methods(self):
- from dashboard_app.views import DashboardDispatcher as dispatcher
- expected_methods = []
- for name in dispatcher.system_listMethods():
- expected_methods.append({
- 'name': name,
- 'signature': dispatcher.system_methodSignature(name),
- 'help': dispatcher.system_methodHelp(name)
- })
- response = self.client.get(self.endpoint_path)
- self.assertEqual(response.context['methods'], expected_methods)
-
- def test_get_request_shows_help(self):
- response = self.client.get(self.endpoint_path)
- self.assertTemplateUsed(response, "dashboard_app/api.html")
-
- def test_empty_post_request_shows_help(self):
- response = self.client.post(self.endpoint_path)
- self.assertTemplateUsed(response, "dashboard_app/api.html")
-
- def test_version(self):
- from dashboard_app import __version__
- self.assertEqual(self.xml_rpc_call('version'),
- ".".join(map(str, __version__)))
-
-
class DashboardAPIStreamsTests(DashboardXMLRPCViewsTestCase):
scenarios = [
=== modified file 'dashboard_app/tests/other/dataview.py'
@@ -19,11 +19,12 @@
import unittest
from mocker import Mocker, expect
+from testtools import TestCase
from dashboard_app.dataview import DataView
-class DataViewHandlerTests(unittest.TestCase):
+class DataViewHandlerTests(TestCase):
text = """
<data-view name="foo">
@@ -43,6 +44,7 @@
"""
def setUp(self):
+ super(DataViewHandlerTests, self).setUp()
self.dataview = DataView.load_from_xml(self.text)
def test_name_parsed_ok(self):
@@ -74,7 +76,7 @@
self.assertEqual(arg.help, "sorting order")
-class DataViewConnectionTests(unittest.TestCase):
+class DataViewConnectionTests(TestCase):
def test_get_connection_without_sandbox(self):
# Mock connections['dataview'] to raise ConnectionDoesNotExist
=== modified file 'dashboard_app/views.py'
@@ -42,23 +42,9 @@
TestResult,
TestRun,
)
-from dashboard_app.xmlrpc import DashboardAPI
from dashboard_app.bread_crumbs import BreadCrumb, BreadCrumbTrail
-def _get_dashboard_dispatcher():
- """
- Build dashboard XML-RPC dispatcher.
- """
- dispatcher = DjangoXMLRPCDispatcher()
- dispatcher.register_instance(DashboardAPI())
- dispatcher.register_introspection_functions()
- return dispatcher
-
-
-DashboardDispatcher = _get_dashboard_dispatcher()
-
-
def _get_queryset(klass):
"""
Returns a QuerySet from a Model, Manager, or QuerySet. Created to make
@@ -97,41 +83,11 @@
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
-# Original inspiration from:
-# Brendan W. McAdams <brendan.mcadams@thewintergrp.com>
-def xml_rpc_handler(request, dispatcher):
- """
- XML-RPC handler.
-
- If post data is defined, it assumes it's XML-RPC and tries to
- process as such. Empty POST request and GET requests assumes you're
- viewing from a browser and tells you about the service.
- """
- if len(request.POST):
- raw_data = request.raw_post_data
- response = HttpResponse(mimetype="application/xml")
- result = dispatcher._marshaled_dispatch(raw_data)
- response.write(result)
- response['Content-length'] = str(len(response.content))
- return response
- else:
- methods = [{
- 'name': method,
- 'signature': dispatcher.system_methodSignature(method),
- 'help': dispatcher.system_methodHelp(method)}
- for method in dispatcher.system_listMethods()]
- return render_to_response(
- 'dashboard_app/api.html', {
- 'methods': methods,
- 'dashboard_url': "http://{domain}".format(
- domain = Site.objects.get_current().domain)
- }, RequestContext(request)
- )
-
-
@csrf_exempt
def dashboard_xml_rpc_handler(request):
- return xml_rpc_handler(request, DashboardDispatcher)
+ from dashboard_app.xmlrpc import legacy_mapper
+ from linaro_django_xmlrpc.views import handler
+ return handler(request, legacy_mapper)
@BreadCrumb("Dashboard")
=== modified file 'dashboard_app/xmlrpc.py'
@@ -26,6 +26,8 @@
from django.contrib.auth.models import User
from django.db import IntegrityError, DatabaseError
+from linaro_django_xmlrpc.models import ExposedAPI
+from linaro_django_xmlrpc.models import Mapper
from dashboard_app import __version__
from dashboard_app.dataview import DataView, DataViewRepository
@@ -48,7 +50,7 @@
NOT_IMPLEMENTED = 501
-class DashboardAPI(object):
+class DashboardAPI(ExposedAPI):
"""
Dashboard API object.
@@ -139,17 +141,16 @@
- team streams are accessible by team members
"""
- user = None
try:
logging.debug("Getting bundle stream")
- bundle_stream = BundleStream.objects.accessible_by_principal(user).get(pathname=pathname)
+ bundle_stream = BundleStream.objects.accessible_by_principal(self.user).get(pathname=pathname)
except BundleStream.DoesNotExist:
logging.debug("Bundle stream does not exists, aborting")
raise xmlrpclib.Fault(errors.NOT_FOUND,
"Bundle stream not found")
try:
logging.debug("Creating bundle object")
- bundle = Bundle.objects.create_with_content(bundle_stream, user, content_filename, content)
+ bundle = Bundle.objects.create_with_content(bundle_stream, self.user, content_filename, content)
except (IntegrityError, ValueError) as exc:
logging.debug("Raising xmlrpclib.Fault(errors.CONFLICT)")
raise xmlrpclib.Fault(errors.CONFLICT, str(exc))
@@ -203,10 +204,9 @@
- personal streams are accessible by owners
- team streams are accessible by team members
"""
- user = None
try:
bundle = Bundle.objects.get(content_sha1=content_sha1)
- if not bundle.bundle_stream.is_accessible_by(user):
+ if not bundle.bundle_stream.is_accessible_by(self.user):
raise Bundle.DoesNotExist()
except Bundle.DoesNotExist:
raise xmlrpclib.Fault(errors.NOT_FOUND,
@@ -259,8 +259,7 @@
- personal streams are accessible by owners
- team streams are accessible by team members
"""
- user = None
- bundle_streams = BundleStream.objects.accessible_by_principal(user)
+ bundle_streams = BundleStream.objects.accessible_by_principal(self.user)
return [{
'pathname': bundle_stream.pathname,
'name': bundle_stream.name,
@@ -323,9 +322,8 @@
- personal streams are accessible by owners
- team streams are accessible by team members
"""
- user = None
try:
- bundle_stream = BundleStream.objects.accessible_by_principal(user).get(pathname=pathname)
+ bundle_stream = BundleStream.objects.accessible_by_principal(self.user).get(pathname=pathname)
except BundleStream.DoesNotExist:
raise xmlrpclib.Fault(errors.NOT_FOUND, "Bundle stream not found")
return [{
@@ -431,6 +429,7 @@
except IntegrityError:
raise xmlrpclib.Fault(errors.CONFLICT, "Stream with the specified pathname already exists")
else:
+ # TODO: Make this constraint unnecessary
raise xmlrpclib.Fault(errors.FORBIDDEN, "Only anonymous streams can be constructed")
return bundle_stream.pathname
@@ -583,3 +582,10 @@
"type": item[1]
} for item in columns]
}
+
+
+
+# Mapper used by the legacy URL
+legacy_mapper = Mapper()
+legacy_mapper.register_introspection_methods()
+legacy_mapper.register(DashboardAPI, '')
=== modified file 'setup.py'
@@ -54,6 +54,7 @@
'lava-server >= 0.2.1',
'linaro-dashboard-bundle >= 1.5.2',
'linaro-django-pagination >= 2.0.2',
+ 'linaro-django-xmlrpc >= 0.3.2',
'linaro-json >= 2.0.1', # TODO: use json-schema-validator
'pygments >= 1.2',
'south >= 0.7.3',