diff --git a/api/internal/enterprise_urls.py b/api/internal/enterprise_urls.py index 1fc7d509fa..cd8448b546 100644 --- a/api/internal/enterprise_urls.py +++ b/api/internal/enterprise_urls.py @@ -1,16 +1,12 @@ from django.urls import include, path -from api.internal.self_hosted.views import SettingsViewSet, UserViewSet -from utils.routers import OptionalTrailingSlashRouter, RetrieveUpdateDestroyRouter +from api.internal.self_hosted.views import UserViewSet +from utils.routers import OptionalTrailingSlashRouter self_hosted_router = OptionalTrailingSlashRouter() self_hosted_router.register(r"users", UserViewSet, basename="selfhosted-users") -settings_router = RetrieveUpdateDestroyRouter() -settings_router.register(r"settings", SettingsViewSet, basename="selfhosted-settings") - urlpatterns = [ path("license/", include("api.internal.license.urls")), - path("", include(settings_router.urls)), path("", include(self_hosted_router.urls)), ] diff --git a/api/internal/owner/views.py b/api/internal/owner/views.py index 14cc625e18..f6503c5c35 100644 --- a/api/internal/owner/views.py +++ b/api/internal/owner/views.py @@ -30,31 +30,6 @@ class OwnerViewSet(OwnerViewSetMixin, mixins.RetrieveModelMixin): serializer_class = OwnerSerializer -class InvoiceViewSet( - viewsets.GenericViewSet, - mixins.ListModelMixin, - mixins.RetrieveModelMixin, - OwnerPropertyMixin, -): - serializer_class = StripeInvoiceSerializer - permission_classes = [MemberOfOrgPermissions] - pagination_class = None - - def get_queryset(self): - return BillingService( - requesting_user=self.request.current_owner - ).list_filtered_invoices(self.owner, 100) - - def get_object(self): - invoice_id = self.kwargs.get("pk") - invoice = BillingService( - requesting_user=self.request.current_owner - ).get_invoice(self.owner, invoice_id) - if not invoice: - raise NotFound(f"Invoice {invoice_id} does not exist for that account") - return invoice - - class AccountDetailsViewSet( viewsets.GenericViewSet, mixins.UpdateModelMixin, diff --git a/api/internal/self_hosted/serializers.py b/api/internal/self_hosted/serializers.py index 24f5ce178e..384a02315c 100644 --- a/api/internal/self_hosted/serializers.py +++ b/api/internal/self_hosted/serializers.py @@ -32,20 +32,3 @@ def update(self, instance, validated_data): # re-query for object to get updated `activated` value return self.context["view"].get_queryset().filter(pk=instance.pk).first() - - -class SettingsSerializer(serializers.Serializer): - # this name is used to be consistent with org-level auto activation - plan_auto_activate = serializers.BooleanField() - - seats_used = serializers.IntegerField() - seats_limit = serializers.IntegerField() - - def update(self, instance, validated_data): - if "plan_auto_activate" in validated_data: - if validated_data["plan_auto_activate"] is True: - self_hosted.enable_autoactivation() - else: - self_hosted.disable_autoactivation() - - return self.context["view"]._get_settings() diff --git a/api/internal/self_hosted/views.py b/api/internal/self_hosted/views.py index 29bccd38a3..246030bcbb 100644 --- a/api/internal/self_hosted/views.py +++ b/api/internal/self_hosted/views.py @@ -11,7 +11,7 @@ from .filters import UserFilters from .permissions import AdminPermissions -from .serializers import SettingsSerializer, UserSerializer +from .serializers import UserSerializer class UserViewSet( @@ -63,31 +63,3 @@ def current_update(self, request): serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) - - -class SettingsViewSet( - viewsets.GenericViewSet, - mixins.RetrieveModelMixin, - mixins.UpdateModelMixin, -): - serializer_class = SettingsSerializer - permission_classes = [AdminPermissions] - - def retrieve(self, request, *args, **kwargs): - serializer = self.get_serializer(self._get_settings()) - return Response(serializer.data) - - def update(self, request, *args, **kwargs): - serializer = self.get_serializer( - self._get_settings(), data=request.data, partial=True - ) - serializer.is_valid(raise_exception=True) - serializer.save() - return Response(serializer.data) - - def _get_settings(self): - return { - "plan_auto_activate": self_hosted.is_autoactivation_enabled(), - "seats_used": self_hosted.activated_owners().count(), - "seats_limit": self_hosted.license_seats(), - } diff --git a/api/internal/tests/views/test_invoice_viewset.py b/api/internal/tests/views/test_invoice_viewset.py deleted file mode 100644 index 29cfed4936..0000000000 --- a/api/internal/tests/views/test_invoice_viewset.py +++ /dev/null @@ -1,132 +0,0 @@ -import json -import os -from unittest.mock import patch - -from rest_framework import status -from rest_framework.reverse import reverse -from rest_framework.test import APITestCase -from stripe import InvalidRequestError, StripeError - -from api.internal.tests.test_utils import GetAdminProviderAdapter -from codecov_auth.tests.factories import OwnerFactory -from utils.test_utils import Client - -curr_path = os.path.dirname(__file__) - - -class InvoiceViewSetTests(APITestCase): - def setUp(self): - self.service = "gitlab" - self.current_owner = OwnerFactory(stripe_customer_id="1000") - self.expected_invoice = { - "number": "EF0A41E-0001", - "status": "paid", - "id": "in_19yTU92eZvKYlo2C7uDjvu6v", - "created": 1489789429, - "period_start": 1487370220, - "period_end": 1489789420, - "due_date": None, - "customer_name": "Peer Company", - "customer_address": "6639 Boulevard Dr, Westwood FL 34202 USA", - "currency": "usd", - "amount_paid": 999, - "amount_due": 999, - "amount_remaining": 0, - "total": 999, - "subtotal": 999, - "invoice_pdf": "https://pay.stripe.com/invoice/acct_1032D82eZvKYlo2C/invst_a7KV10HpLw2QxrihgVyuOkOjMZ/pdf", - "line_items": [ - { - "description": "(10) users-pr-inappm", - "amount": 120, - "quantity": 1, - "currency": "usd", - "plan_name": "users-pr-inappm", - "period": {"end": 1521326190, "start": 1518906990}, - } - ], - "footer": None, - "customer_email": "olivia.williams.03@example.com", - "customer_shipping": None, - } - - self.client = Client() - self.client.force_login_owner(self.current_owner) - - def _list(self, kwargs): - return self.client.get(reverse("invoices-list", kwargs=kwargs)) - - def _retrieve(self, kwargs): - return self.client.get(reverse("invoices-detail", kwargs=kwargs)) - - @patch("services.billing.stripe.Invoice.list") - def test_invoices_returns_100_recent_invoices(self, mock_list_filtered_invoices): - with open("./services/tests/samples/stripe_invoice.json") as f: - stripe_invoice_response = json.load(f) - # make it so there's 100 invoices, which is the max stripe returns - stripe_invoice_response["data"] = stripe_invoice_response["data"] * 100 - mock_list_filtered_invoices.return_value = stripe_invoice_response - expected_invoices = [self.expected_invoice] * 100 - - response = self._list( - kwargs={ - "service": self.current_owner.service, - "owner_username": self.current_owner.username, - } - ) - - assert response.status_code == status.HTTP_200_OK - assert len(response.data) == 100 - assert response.data == expected_invoices - - @patch("api.shared.permissions.get_provider") - def test_invoices_returns_404_if_user_not_admin(self, get_provider_mock): - get_provider_mock.return_value = GetAdminProviderAdapter() - owner = OwnerFactory() - response = self._list( - kwargs={"service": owner.service, "owner_username": owner.username} - ) - assert response.status_code == status.HTTP_404_NOT_FOUND - - @patch("services.billing.stripe.Invoice.retrieve") - def test_invoice(self, mock_retrieve_invoice): - with open("./services/tests/samples/stripe_invoice.json") as f: - stripe_invoice_response = json.load(f) - invoice = stripe_invoice_response["data"][0] - invoice["customer"] = self.current_owner.stripe_customer_id - mock_retrieve_invoice.return_value = invoice - response = self._retrieve( - kwargs={ - "service": self.current_owner.service, - "owner_username": self.current_owner.username, - "pk": invoice["id"], - } - ) - assert response.status_code == status.HTTP_200_OK - assert response.data == self.expected_invoice - - @patch("services.billing.stripe.Invoice.retrieve") - def test_when_invoice_not_found(self, mock_retrieve_invoice): - mock_retrieve_invoice.side_effect = InvalidRequestError( - message="not found", param="abc" - ) - response = self._retrieve( - kwargs={ - "service": self.current_owner.service, - "owner_username": self.current_owner.username, - "pk": "abc", - } - ) - assert response.status_code == status.HTTP_404_NOT_FOUND - - @patch("services.billing.stripe.Invoice.retrieve") - def test_when_no_customer_dont_match(self, mock_retrieve_invoice): - mock_retrieve_invoice.return_value = {"customer": "123456789"} - response = self._retrieve( - kwargs={ - "service": self.current_owner.service, - "owner_username": self.current_owner.username, - "pk": "abc", - } - ) - assert response.status_code == status.HTTP_404_NOT_FOUND diff --git a/api/internal/tests/views/test_self_hosted_settings_viewset.py b/api/internal/tests/views/test_self_hosted_settings_viewset.py index 2c6eb85334..2142345e57 100644 --- a/api/internal/tests/views/test_self_hosted_settings_viewset.py +++ b/api/internal/tests/views/test_self_hosted_settings_viewset.py @@ -28,64 +28,3 @@ def test_settings(self): res = self.client.get(reverse("selfhosted-users-list")) # not authenticated assert res.status_code == 403 - - -@override_settings(IS_ENTERPRISE=True, ROOT_URLCONF="api.internal.enterprise_urls") -class SettingsViewsetTestCase(TestCase): - def setUp(self): - self.current_owner = OwnerFactory() - self.client = APIClient() - self.client.force_login_owner(self.current_owner) - - @patch("services.self_hosted.license_seats") - @patch("services.self_hosted.is_autoactivation_enabled") - @patch("services.self_hosted.admin_owners") - def test_settings(self, admin_owners, is_autoactivation_enabled, license_seats): - admin_owners.return_value = Owner.objects.filter(pk__in=[self.current_owner.pk]) - - is_autoactivation_enabled.return_value = False - license_seats.return_value = 5 - - res = self.client.get(reverse("selfhosted-settings-detail")) - assert res.status_code == 200 - assert res.json() == { - "plan_auto_activate": False, - "seats_used": 0, - "seats_limit": 5, - } - - is_autoactivation_enabled.return_value = True - - org = OwnerFactory() - owner = OwnerFactory(organizations=[org.pk]) - activate_owner(owner) - - res = self.client.get(reverse("selfhosted-settings-detail")) - assert res.status_code == 200 - assert res.json() == { - "plan_auto_activate": True, - "seats_used": 1, - "seats_limit": 5, - } - - @patch("services.self_hosted.admin_owners") - def test_settings_update(self, admin_owners): - admin_owners.return_value = Owner.objects.filter(pk__in=[self.current_owner.pk]) - - res = self.client.patch( - reverse("selfhosted-settings-detail"), - data={"plan_auto_activate": True}, - format="json", - ) - assert res.status_code == 200 - assert res.json()["plan_auto_activate"] == True - assert is_autoactivation_enabled() == True - - res = self.client.patch( - reverse("selfhosted-settings-detail"), - data={"plan_auto_activate": False}, - format="json", - ) - assert res.status_code == 200 - assert res.json()["plan_auto_activate"] == False - assert is_autoactivation_enabled() == False diff --git a/api/internal/urls.py b/api/internal/urls.py index 9f0e4087fa..312eb44523 100644 --- a/api/internal/urls.py +++ b/api/internal/urls.py @@ -10,7 +10,6 @@ from api.internal.feature.views import FeaturesView from api.internal.owner.views import ( AccountDetailsViewSet, - InvoiceViewSet, OwnerViewSet, UserViewSet, ) @@ -29,7 +28,6 @@ owner_artifacts_router = OptionalTrailingSlashRouter() owner_artifacts_router.register(r"users", UserViewSet, basename="users") -owner_artifacts_router.register(r"invoices", InvoiceViewSet, basename="invoices") account_details_router = RetrieveUpdateDestroyRouter() account_details_router.register(