diff --git a/docs/topics/api/misc.rst b/docs/topics/api/misc.rst index 2bb32d3db5..74f2a87ab7 100644 --- a/docs/topics/api/misc.rst +++ b/docs/topics/api/misc.rst @@ -85,6 +85,22 @@ Fields that can be updated: * *display_name* +.. http:get:: /api/v1/account/installed/ + + Returns a list of the installed apps for the currently logged in user. This + ignores any reviewer or developer installed apps. + + .. note:: Requires authentication. + + **Request** + + The standard :ref:`list-query-params-label`. + + **Response** + + :param meta: :ref:`meta-response-label`. + :param objects: A :ref:`listing ` of :ref:`apps `. + Categories ========== diff --git a/mkt/account/api.py b/mkt/account/api.py index 191d896868..635e6dcfef 100644 --- a/mkt/account/api.py +++ b/mkt/account/api.py @@ -18,6 +18,9 @@ from mkt.api.authentication import (OAuthAuthentication, from mkt.api.base import (CORSResource, GenericObject, MarketplaceModelResource, MarketplaceResource, PotatoCaptchaResource) +from mkt.api.resources import AppResource +from mkt.constants.apps import INSTALL_TYPE_USER +from mkt.webapps.models import Webapp from users.models import UserProfile from users.views import browserid_login @@ -46,6 +49,21 @@ class AccountResource(CORSResource, MarketplaceModelResource): return obj +class InstalledResource(AppResource): + + class Meta: + authentication = (SharedSecretAuthentication(), OAuthAuthentication()) + authorization = OwnerAuthorization() + detail_allowed_methods = [] + list_allowed_methods = ['get'] + resource_name = 'installed' + slug_lookup = None + + def obj_get_list(self, request=None, **kwargs): + return Webapp.objects.filter(installed__user=request.amo_user, + installed__install_type=INSTALL_TYPE_USER) + + class LoginResource(CORSResource, MarketplaceResource): class Meta: diff --git a/mkt/account/tests/test_api.py b/mkt/account/tests/test_api.py index bde35d3dd9..e41920ac7c 100644 --- a/mkt/account/tests/test_api.py +++ b/mkt/account/tests/test_api.py @@ -88,6 +88,44 @@ class TestAccount(BaseOAuth): eq_(res.status_code, 403) +class TestInstalled(BaseOAuth): + fixtures = fixture('user_2519', 'user_10482', 'webapp_337141') + + def setUp(self): + super(TestInstalled, self).setUp(api_name='account') + self.list_url = list_url('installed') + self.user = UserProfile.objects.get(pk=2519) + + def test_verbs(self): + self._allowed_verbs(self.list_url, ('get')) + + def test_not_allowed(self): + eq_(self.anon.get(self.list_url).status_code, 401) + + def test_installed(self): + ins = Installed.objects.create(user=self.user, addon_id=337141) + res = self.client.get(self.list_url) + eq_(res.status_code, 200, res.content) + data = json.loads(res.content) + eq_(data['meta']['total_count'], 1) + eq_(data['objects'][0]['id'], str(ins.addon.pk)) + + def not_there(self): + res = self.client.get(self.list_url) + eq_(res.status_code, 200, res.content) + data = json.loads(res.content) + eq_(data['meta']['total_count'], 0) + + def test_installed_other(self): + Installed.objects.create(user_id=10482, addon_id=337141) + self.not_there() + + def test_installed_reviewer(self): + Installed.objects.create(user=self.user, addon_id=337141, + install_type=INSTALL_TYPE_REVIEWER) + self.not_there() + + class FakeUUID(object): hex = '000000' diff --git a/mkt/account/urls.py b/mkt/account/urls.py index 3093381f1b..a134fdae18 100644 --- a/mkt/account/urls.py +++ b/mkt/account/urls.py @@ -5,7 +5,8 @@ from tastypie.api import Api from amo.decorators import login_required from lib.misc.urlconf_decorator import decorate -from mkt.account.api import AccountResource, FeedbackResource, LoginResource +from mkt.account.api import (AccountResource, FeedbackResource, + InstalledResource, LoginResource) from . import views settings_patterns = patterns('', @@ -50,6 +51,7 @@ users_patterns = patterns('', account = Api(api_name='account') account.register(AccountResource()) account.register(FeedbackResource()) +account.register(InstalledResource()) account.register(LoginResource()) api_patterns = patterns('',