stand up an app creation api (bug 704206)

This commit is contained in:
Andy McKay 2011-11-24 14:37:37 -08:00
Родитель 77f49f4a99
Коммит abe801e7d6
4 изменённых файлов: 102 добавлений и 6 удалений

Просмотреть файл

@ -1,5 +1,7 @@
import functools
import json
from django.conf import settings
from django.db import transaction
import commonware.log
@ -7,16 +9,20 @@ import happyforms
from piston.handler import AnonymousBaseHandler, BaseHandler
from piston.utils import rc
from tower import ugettext as _
import waffle
import amo
from access import acl
from addons.forms import AddonForm
from addons.models import Addon, AddonUser
from amo.utils import paginate
from devhub.forms import LicenseForm
from devhub.forms import LicenseForm, NewManifestForm
from devhub import tasks
from files.models import FileUpload, Platform
from users.models import UserProfile
from versions.forms import XPIForm
from versions.models import Version, ApplicationsVersions
from webapps.models import Webapp
log = commonware.log.getLogger('z.api')
@ -151,6 +157,49 @@ class AddonsHandler(BaseHandler):
'count': paginator.paginator.count}
class AppsHandler(AddonsHandler):
allowed_methods = ('GET', 'POST')
model = Webapp
fields = ('id', 'name', 'manifest_url', 'status', 'app_slug')
exclude = ('highest_status', 'icon_type')
@transaction.commit_on_success
def create(self, request):
if not waffle.flag_is_active(request, 'accept-webapps'):
return rc.BAD_REQUEST
form = NewManifestForm(request.POST)
if form.is_valid():
# This feels like an awful lot of work.
# But first upload the file and do the validation.
upload = FileUpload.objects.create()
tasks.fetch_manifest(form.cleaned_data['manifest'], upload.pk)
# We must reget the object here since the above has
# saved changes to the object.
upload = FileUpload.uncached.get(pk=upload.pk)
# Check it validated correctly.
if settings.VALIDATE_ADDONS:
validation = json.loads(upload.validation)
if validation['errors']:
response = rc.BAD_REQUEST
response.write(validation)
return response
# Fetch the addon, the icon and set the user.
addon = Addon.from_upload(upload,
[Platform.objects.get(id=amo.PLATFORM_ALL.id)])
tasks.fetch_icon(addon)
AddonUser(addon=addon, user=request.amo_user).save()
addon.update(status=amo.STATUS_PENDING if
settings.WEBAPPS_RESTRICTED else amo.STATUS_PUBLIC)
else:
return _form_error(form)
return addon
class ApplicationsVersionsHandler(AnonymousBaseHandler):
model = ApplicationsVersions
allowed_methods = ('GET', )
@ -276,7 +325,7 @@ class AMOBaseHandler(BaseHandler):
def delete(self, request, id):
try:
return self.model.objects.get(pk=id).delete()
except Performance.DoesNotExist:
except self.model.DoesNotExist:
return rc.NOT_HERE
def create(self, request):
@ -289,7 +338,7 @@ class AMOBaseHandler(BaseHandler):
if id:
try:
return self.model.objects.get(pk=id)
except Performance.DoesNotExist:
except self.model.DoesNotExist:
return rc.NOT_HERE
else:
paginator = paginate(request, self.model.objects.all())
@ -300,7 +349,7 @@ class AMOBaseHandler(BaseHandler):
def update(self, request, id):
try:
obj = self.model.objects.get(pk=id)
except Performance.DoesNotExist:
except self.model.DoesNotExist:
return rc.NOT_HERE
form = self.get_form(request.POST, instance=obj)
if form.is_valid():

Просмотреть файл

@ -34,6 +34,7 @@ from django.test.client import (encode_multipart, Client, FakePayload,
import oauth2 as oauth
from mock import Mock, patch
from nose import SkipTest
from nose.tools import eq_
from piston.models import Consumer
@ -202,6 +203,9 @@ class BaseOAuth(TestCase):
def _login(self):
self.client.login(username='admin@mozilla.com', password='password')
class TestBaseOAuth(BaseOAuth):
def test_accepted(self):
self.assertRaises(AssertionError, get_request_token,
self.accepted_consumer)
@ -748,6 +752,46 @@ class TestAddon(BaseOAuth):
eq_(json.loads(r.content)['count'], 0)
@patch.object(settings, 'VALIDATE_ADDONS', False)
class TestCreateApp(BaseOAuth):
def setUp(self):
super(TestCreateApp, self).setUp()
patcher = patch('devhub.tasks._fetch_content')
response_mock = Mock()
response_mock.read.return_value = '{"name": "Some App"}'
response_mock.headers = {'Content-Type':
'application/x-web-app-manifest+json'}
self.urlopen_mock = patcher.start()
self.urlopen_mock.return_value = response_mock
self.addCleanup(patcher.stop)
patcher = patch('waffle.flag_is_active')
patcher.start().return_value = True
self.addCleanup(patcher.stop)
def make_create_request(self, data):
return client.post('api.apps', self.accepted_consumer, self.token,
data=data)
def test_create_app(self):
res = self.make_create_request({'manifest': 'http://x.com/a.webapp'})
eq_(res.status_code, 200)
def test_no_manifest(self):
res = self.make_create_request({'manifest': ''})
eq_(res.status_code, 400)
assert 'manifest' in res.content
def test_validation_fails(self):
raise SkipTest
# TODO(andym) figure out how to stop it doing validation, but
# coping with a bad validation.
class TestPerformanceAPI(BaseOAuth):
fixtures = ['base/users']

Просмотреть файл

@ -67,6 +67,7 @@ for regexp in list_regexps:
ad = {'authentication': authentication.AMOOAuthAuthentication(two_legged=True)}
user_resource = Resource(handler=handlers.UserHandler, **ad)
addons_resource = Resource(handler=handlers.AddonsHandler, **ad)
apps_resource = Resource(handler=handlers.AppsHandler, **ad)
version_resource = Resource(handler=handlers.VersionsHandler, **ad)
piston_patterns = patterns('',
@ -76,7 +77,9 @@ piston_patterns = patterns('',
url(r'^addon/%s/versions$' % ADDON_ID, version_resource,
name='api.versions'),
url(r'^addon/%s/version/(?P<version_id>\d+)$' % ADDON_ID,
version_resource, name='api.version')
version_resource, name='api.version'),
url(r'^apps/$', apps_resource, name='api.apps'),
url(r'^app/%s$' % ADDON_ID, apps_resource, name='api.app'),
)
urlpatterns = patterns('',

Просмотреть файл

@ -185,7 +185,7 @@ class File(amo.models.OnChangeMixin, amo.models.ModelBase):
data = {'sdkVersion': None, 'builderVersion': None}
try:
zip_ = zipfile.ZipFile(path)
except zipfile.BadZipfile:
except (zipfile.BadZipfile, IOError):
# This path is not an XPI. It's probably an app manifest.
return data
name = 'harness-options.json'