diff --git a/endpoints/api.py b/endpoints/api.py index 8160c730f..e49189370 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -183,7 +183,7 @@ def get_logged_in_user(): @api.route('/user/private', methods=['GET']) @api_login_required @internal_api_call -def get_user_private_count(): +def get_user_private_allowed(): user = current_user.db_user() private_repos = model.get_private_repo_count(user.username) repos_allowed = 0 @@ -197,7 +197,7 @@ def get_user_private_count(): return jsonify({ 'privateCount': private_repos, - 'reposAllowed': repos_allowed + 'privateAllowed': (private_repos < repos_allowed) }) @@ -729,12 +729,16 @@ def get_organization_member(orgname, membername): @api.route('/organization//private', methods=['GET']) @api_login_required @internal_api_call +@org_api_call('get_user_private_allowed') def get_organization_private_allowed(orgname): permission = CreateRepositoryPermission(orgname) if permission.can(): organization = model.get_organization(orgname) - private_repos = model.get_private_repo_count(organization.username) + data = { + 'privateAllowed': False + } + if organization.stripe_id: cus = stripe.Customer.retrieve(organization.stripe_id) if cus.subscription: @@ -743,13 +747,13 @@ def get_organization_private_allowed(orgname): if plan: repos_allowed = plan['privateRepos'] - return jsonify({ - 'privateAllowed': (private_repos < repos_allowed) - }) + data['privateAllowed'] = (private_repos < repos_allowed) + - return jsonify({ - 'privateAllowed': False - }) + if AdministerOrganizationPermission(orgname).can(): + data['privateCount'] = private_repos + + return jsonify(data) abort(403) diff --git a/static/js/app.js b/static/js/app.js index d82bb27a1..59328673e 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -602,10 +602,6 @@ quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'angu planService.getPlans(function(plans) { for (var i = 0; i < plans.length; i++) { var plan = plans[i]; - if (isBusiness && !planService.isOrgCompatible(plan)) { - continue; - } - if (plan.privateRepos >= privateCount) { callback(plan); return; @@ -613,7 +609,7 @@ quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'angu } callback(null); - }); + }, /* include personal */!isBusiness); }; planService.getSubscription = function(orgname, success, failure) { @@ -2077,8 +2073,8 @@ quayApp.directive('headerBar', function () { return; } - ApiService.getUserPrivateCount().then(function(resp) { - $scope.overPlan = resp.privateCount > resp.reposAllowed; + ApiService.getUserPrivateAllowed().then(function(resp) { + $scope.overPlan = !resp['privateAllowed']; }); }; diff --git a/static/js/controllers.js b/static/js/controllers.js index 8a9fb865c..22e56f08d 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -1906,37 +1906,14 @@ function NewRepoCtrl($scope, $location, $http, $timeout, UserService, ApiService var isUserNamespace = (namespace == $scope.user.username); - $scope.checkingPlan = true; $scope.planRequired = null; $scope.isUserNamespace = isUserNamespace; - if (isUserNamespace) { - // Load the user's subscription information in case they want to create a private - // repository. - ApiService.getUserPrivateCount().then(function(resp) { - if (resp.privateCount + 1 > resp.reposAllowed) { - PlanService.getMinimumPlan(resp.privateCount + 1, false, function(minimum) { - $scope.planRequired = minimum; - }); - } + // Determine whether private repositories are allowed for the namespace. + checkPrivateAllowed(); - $scope.checkingPlan = false; - }, function() { - $scope.planRequired = {}; - $scope.checkingPlan = false; - }); - } else { - ApiService.getOrganizationPrivateAllowed(null, {'orgname': namespace}).then(function(resp) { - $scope.planRequired = resp.privateAllowed ? null : {}; - $scope.checkingPlan = false; - }, function() { - $scope.planRequired = {}; - $scope.checkingPlan = false; - }); - - // Auto-set to private repo. - $scope.repo.is_public = '0'; - } + // Default to private repos for organizations. + $scope.repo.is_public = isUserNamespace ? '1' : '0'; }); $scope.changeNamespace = function(namespace) { @@ -2015,7 +1992,35 @@ function NewRepoCtrl($scope, $location, $http, $timeout, UserService, ApiService } }; - PlanService.changePlan($scope, null, $scope.planRequired.stripeId, callbacks); + var namespace = $scope.isUserNamespace ? null : $scope.repo.namespace; + PlanService.changePlan($scope, namespace, $scope.planRequired.stripeId, callbacks); + }; + + var checkPrivateAllowed = function() { + if (!$scope.repo || !$scope.repo.namespace) { return; } + + $scope.checkingPlan = true; + + var isUserNamespace = $scope.isUserNamespace; + ApiService.getPrivateAllowed(isUserNamespace ? null : $scope.repo.namespace).then(function(resp) { + $scope.checkingPlan = false; + + if (resp['privateAllowed']) { + $scope.planRequired = null; + return; + } + + if (resp['privateCount'] == null) { + // Organization where we are not the admin. + $scope.planRequired = {}; + return; + } + + // Otherwise, lookup the matching plan. + PlanService.getMinimumPlan(resp['privateCount'] + 1, !isUserNamespace, function(minimum) { + $scope.planRequired = minimum; + }); + }); }; var subscribedToPlan = function(sub) { @@ -2025,16 +2030,7 @@ function NewRepoCtrl($scope, $location, $http, $timeout, UserService, ApiService PlanService.getPlan(sub.plan, function(subscribedPlan) { $scope.subscribedPlan = subscribedPlan; $scope.planRequired = null; - - // Check to see if the current plan allows for an additional private repository to - // be created. - var privateAllowed = $scope.subscription.usedPrivateRepos < $scope.subscribedPlan.privateRepos; - if (!privateAllowed) { - // If not, find the minimum repository that does. - PlanService.getMinimumPlan($scope.subscription.usedPrivateRepos + 1, !$scope.isUserNamespace, function(minimum) { - $scope.planRequired = minimum; - }); - } + checkPrivateAllowed(); }); }; } diff --git a/static/partials/new-repo.html b/static/partials/new-repo.html index 7eb73d86b..25f828620 100644 --- a/static/partials/new-repo.html +++ b/static/partials/new-repo.html @@ -63,25 +63,27 @@ -
+
- In order to make this repository private, you’ll need to upgrade your plan to + In order to make this repository private + under your personal namespace + under the organization {{ repo.namespace }}, you will need to upgrade your plan to {{ planRequired.title }} . This will cost ${{ planRequired.price / 100 }}/month.
Upgrade now - or did you mean to create this repository + or did you mean to create this repository under {{ user.organizations[0].name }}?
-
+
- This organization has reached its private repository limit. Please contact your administrator. + This organization has reached its private repository limit. Please contact your administrator.
diff --git a/test/test_api_usage.py b/test/test_api_usage.py index 04f7257c3..04a999f1d 100644 --- a/test/test_api_usage.py +++ b/test/test_api_usage.py @@ -128,18 +128,18 @@ class TestLoggedInUser(ApiTestCase): assert json['username'] == READ_ACCESS_USER -class TestGetUserPrivateCount(ApiTestCase): +class TestGetUserPrivateAllowed(ApiTestCase): def test_nonallowed(self): self.login(READ_ACCESS_USER) - json = self.getJsonResponse('api.get_user_private_count') + json = self.getJsonResponse('api.get_user_private_allowed') assert json['privateCount'] == 0 - assert json['reposAllowed'] == 0 + assert not json['privateAllowed'] def test_allowed(self): self.login(ADMIN_ACCESS_USER) - json = self.getJsonResponse('api.get_user_private_count') + json = self.getJsonResponse('api.get_user_private_allowed') assert json['privateCount'] == 6 - assert json['reposAllowed'] > 0 + assert json['privateAllowed'] class TestConvertToOrganization(ApiTestCase):