From 6467e24ba2b9cf4eaf086f7b4f234d5279e61136 Mon Sep 17 00:00:00 2001 From: yackob03 Date: Mon, 11 Nov 2013 19:02:42 -0500 Subject: [PATCH 1/3] All for free user to free business migration. --- endpoints/api.py | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/endpoints/api.py b/endpoints/api.py index 88305f213..bd558de72 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -1190,7 +1190,8 @@ def subscribe_api(): token = request_data['token'] if 'token' in request_data else None user = current_user.db_user() return subscribe(user, plan, token, USER_PLANS) - + + def subscribe(user, plan, token, accepted_plans): plan_found = None for plan_obj in accepted_plans: @@ -1202,16 +1203,25 @@ def subscribe(user, plan, token, accepted_plans): private_repos = model.get_private_repo_count(user.username) - if not user.stripe_id: - # Create the customer and plan simultaneously - card = token - cus = stripe.Customer.create(email=user.email, plan=plan, card=card) - user.stripe_id = cus.id - user.save() + # This is the default response + response_json = { + 'plan': plan, + 'usedPrivateRepos': private_repos, + } + status_code = 200 - resp = jsonify(subscription_view(cus.subscription, private_repos)) - resp.status_code = 201 - return resp + if not user.stripe_id: + # Check if a non-paying user is trying to subscribe to a free plan + if not plan_found['price'] == 0: + # They want a real paying plan, create the customerand plan + # simultaneously + card = token + cus = stripe.Customer.create(email=user.email, plan=plan, card=card) + user.stripe_id = cus.id + user.save() + + response_json = subscription_view(cus.subscription, private_repos) + status_code = 201 else: # Change the plan @@ -1223,11 +1233,6 @@ def subscribe(user, plan, token, accepted_plans): cus.cancel_subscription() cus.save() - response_json = { - 'plan': plan, - 'usedPrivateRepos': private_repos, - } - else: cus.plan = plan # User may have been a previous customer who is resubscribing @@ -1237,7 +1242,9 @@ def subscribe(user, plan, token, accepted_plans): cus.save() response_json = subscription_view(cus.subscription, private_repos) - return jsonify(response_json) + resp = jsonify(response_json) + resp.status_code = status_code + return resp @app.route('/api/organization//plan', methods=['PUT']) From 07b9128ab6431e5e481633141123e580a60ed0e6 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Mon, 11 Nov 2013 19:03:18 -0500 Subject: [PATCH 2/3] Return 403 if the user logged in is now an org and handle it on the client --- endpoints/api.py | 8 +++++--- static/js/app.js | 9 ++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/endpoints/api.py b/endpoints/api.py index 88305f213..d13f8b730 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -40,6 +40,10 @@ def api_login_required(f): def decorated_view(*args, **kwargs): if not current_user.is_authenticated(): abort(401) + + if current_user.db_user().organization: + abort(403) + return f(*args, **kwargs) return decorated_view @@ -78,7 +82,7 @@ def get_logged_in_user(): 'can_create_repo': admin_org.can() or CreateRepositoryPermission(o.username).can() } - if current_user.is_anonymous(): + if current_user.is_anonymous() or current_user.db_user().organization: return jsonify({'anonymous': True}) user = current_user.db_user() @@ -223,9 +227,7 @@ def conduct_signin(username, password): @api_login_required def logout(): logout_user() - identity_changed.send(app, identity=AnonymousIdentity()) - return make_response('Success', 200) diff --git a/static/js/app.js b/static/js/app.js index 8fb7773be..6298544d0 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -867,7 +867,14 @@ quayApp.directive('ngBlur', function() { }; }); -quayApp.run(['$location', '$rootScope', function($location, $rootScope) { +quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', function($location, $rootScope, Restangular, UserService) { + Restangular.setResponseInterceptor(function(data, operation, what, url, response, deferred) { + if (response.status == 403) { + UserService.load(); + } + return data; + }); + $rootScope.$on('$routeChangeSuccess', function (event, current, previous) { if (current.$$route.title) { $rootScope.title = current.$$route.title; From b8dc051705a134d8391bce24f727938c4d033f97 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Mon, 11 Nov 2013 19:26:56 -0500 Subject: [PATCH 3/3] Change 403 handling to 401 and have a modal dialog (that cannot be removed) display when the user's session has expired. This forces them to reload the page, and thus reset all the state. --- endpoints/api.py | 9 ++++++--- static/js/app.js | 16 +++++++++++----- templates/index.html | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/endpoints/api.py b/endpoints/api.py index 493f50d0d..e4fe31765 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -41,8 +41,8 @@ def api_login_required(f): if not current_user.is_authenticated(): abort(401) - if current_user.db_user().organization: - abort(403) + if current_user and current_user.db_user() and current_user.db_user().organization: + abort(401) return f(*args, **kwargs) return decorated_view @@ -82,10 +82,13 @@ def get_logged_in_user(): 'can_create_repo': admin_org.can() or CreateRepositoryPermission(o.username).can() } - if current_user.is_anonymous() or current_user.db_user().organization: + if current_user.is_anonymous(): return jsonify({'anonymous': True}) user = current_user.db_user() + if not user or user.organization: + return jsonify({'anonymous': True}) + organizations = model.get_user_organizations(user.username) return jsonify({ diff --git a/static/js/app.js b/static/js/app.js index 6298544d0..2a0d08236 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -60,7 +60,7 @@ quayApp = angular.module('quay', ['restangular', 'angularMoment', 'angulartics', var userService = {} - userService.load = function() { + userService.load = function(opt_callback) { var userFetch = Restangular.one('user/'); userFetch.get().then(function(loadedUser) { userResponse = loadedUser; @@ -76,6 +76,10 @@ quayApp = angular.module('quay', ['restangular', 'angularMoment', 'angulartics', '$created': new Date() }) } + + if (opt_callback) { + opt_callback(); + } }); }; @@ -868,11 +872,13 @@ quayApp.directive('ngBlur', function() { }); quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', function($location, $rootScope, Restangular, UserService) { - Restangular.setResponseInterceptor(function(data, operation, what, url, response, deferred) { - if (response.status == 403) { - UserService.load(); + Restangular.setErrorInterceptor(function(response) { + if (response.status == 401) { + $('#sessionexpiredModal').modal({}); + return false; } - return data; + + return true; }); $rootScope.$on('$routeChangeSuccess', function (event, current, previous) { diff --git a/templates/index.html b/templates/index.html index 00c387d59..664570e5d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -30,4 +30,22 @@ {% block body_content %}
+ + + + + {% endblock %}