Check subscription status on login.
This commit is contained in:
parent
dcbefc33ae
commit
07691db874
@ -64,7 +64,7 @@ class PillarServer(Eve):
|
|||||||
self.load_config()
|
self.load_config()
|
||||||
|
|
||||||
# Configure authentication
|
# Configure authentication
|
||||||
self._login_manager = auth.config_login_manager(self)
|
self.login_manager = auth.config_login_manager(self)
|
||||||
self.oauth_blender_id = auth.config_oauth_login(self)
|
self.oauth_blender_id = auth.config_oauth_login(self)
|
||||||
|
|
||||||
self._config_caching()
|
self._config_caching()
|
||||||
|
51
pillar/auth/subscriptions.py
Normal file
51
pillar/auth/subscriptions.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
"""Cloud subscription info.
|
||||||
|
|
||||||
|
Connects to the external subscription server to obtain user info.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
import requests
|
||||||
|
from requests.adapters import HTTPAdapter
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_user(email):
|
||||||
|
"""Returns the user info dict from the external subscriptions management server.
|
||||||
|
|
||||||
|
:returns: the store user info, or None if the user can't be found or there
|
||||||
|
was an error communicating. A dict like this is returned:
|
||||||
|
{
|
||||||
|
"shop_id": 700,
|
||||||
|
"cloud_access": 1,
|
||||||
|
"paid_balance": 314.75,
|
||||||
|
"balance_currency": "EUR",
|
||||||
|
"start_date": "2014-08-25 17:05:46",
|
||||||
|
"expiration_date": "2016-08-24 13:38:45",
|
||||||
|
"subscription_status": "wc-active",
|
||||||
|
"expiration_date_approximate": true
|
||||||
|
}
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
external_subscriptions_server = current_app.config['EXTERNAL_SUBSCRIPTIONS_MANAGEMENT_SERVER']
|
||||||
|
|
||||||
|
log.debug('Connecting to store at %s?blenderid=%s', external_subscriptions_server, email)
|
||||||
|
|
||||||
|
# Retry a few times when contacting the store.
|
||||||
|
s = requests.Session()
|
||||||
|
s.mount(external_subscriptions_server, HTTPAdapter(max_retries=5))
|
||||||
|
r = s.get(external_subscriptions_server, params={'blenderid': email},
|
||||||
|
verify=current_app.config['TLS_CERT_FILE'])
|
||||||
|
|
||||||
|
if r.status_code != 200:
|
||||||
|
log.warning("Error communicating with %s, code=%i, unable to check "
|
||||||
|
"subscription status of user %s",
|
||||||
|
external_subscriptions_server, r.status_code, email)
|
||||||
|
return None
|
||||||
|
|
||||||
|
store_user = r.json()
|
||||||
|
return store_user
|
||||||
|
|
@ -2,6 +2,8 @@ import os.path
|
|||||||
from os import getenv
|
from os import getenv
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
import requests.certs
|
||||||
|
|
||||||
RFC1123_DATE_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
|
RFC1123_DATE_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
|
||||||
PILLAR_SERVER_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
PILLAR_SERVER_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
@ -137,3 +139,6 @@ URLER_SERVICE_AUTH_TOKEN = None
|
|||||||
BLENDER_CLOUD_ADDON_VERSION = '1.4'
|
BLENDER_CLOUD_ADDON_VERSION = '1.4'
|
||||||
|
|
||||||
EXTERNAL_SUBSCRIPTIONS_MANAGEMENT_SERVER = 'https://store.blender.org/api/'
|
EXTERNAL_SUBSCRIPTIONS_MANAGEMENT_SERVER = 'https://store.blender.org/api/'
|
||||||
|
|
||||||
|
# Certificate file for communication with other systems.
|
||||||
|
TLS_CERT_FILE = requests.certs.where()
|
||||||
|
@ -6,7 +6,7 @@ from flask import (abort, Blueprint, current_app, flash, redirect,
|
|||||||
render_template, request, session, url_for)
|
render_template, request, session, url_for)
|
||||||
from flask_login import login_required, login_user, logout_user, current_user
|
from flask_login import login_required, login_user, logout_user, current_user
|
||||||
from flask_oauthlib.client import OAuthException
|
from flask_oauthlib.client import OAuthException
|
||||||
from pillar.auth import UserClass
|
from pillar.auth import UserClass, subscriptions
|
||||||
from pillar.web import system_util
|
from pillar.web import system_util
|
||||||
from .forms import UserProfileForm
|
from .forms import UserProfileForm
|
||||||
from .forms import UserSettingsEmailsForm
|
from .forms import UserSettingsEmailsForm
|
||||||
@ -55,13 +55,12 @@ def blender_id_authorized():
|
|||||||
|
|
||||||
user = UserClass(oauth_resp['access_token'])
|
user = UserClass(oauth_resp['access_token'])
|
||||||
login_user(user)
|
login_user(user)
|
||||||
# user = load_user(current_user.id)
|
current_app.login_manager.reload_user() # This ensures that flask_login.current_user is set.
|
||||||
|
|
||||||
if user is not None:
|
if current_user is not None:
|
||||||
pass
|
|
||||||
# Check with the store for user roles. If the user has an active
|
# Check with the store for user roles. If the user has an active
|
||||||
# subscription, we apply the 'subscriber' role
|
# subscription, we apply the 'subscriber' role
|
||||||
# user_roles_update(user.objectid)
|
user_roles_update(current_user.objectid)
|
||||||
|
|
||||||
next_after_login = session.get('next_after_login')
|
next_after_login = session.get('next_after_login')
|
||||||
if next_after_login:
|
if next_after_login:
|
||||||
@ -179,9 +178,9 @@ def settings_billing():
|
|||||||
for group_id in user.groups:
|
for group_id in user.groups:
|
||||||
group = Group.find(group_id, api=api)
|
group = Group.find(group_id, api=api)
|
||||||
groups.append(group.name)
|
groups.append(group.name)
|
||||||
external_subscriptions_server = current_app.config['EXTERNAL_SUBSCRIPTIONS_MANAGEMENT_SERVER']
|
|
||||||
r = requests.get(external_subscriptions_server, params={'blenderid': user.email})
|
store_user = subscriptions.fetch_user(user.email)
|
||||||
store_user = r.json()
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'users/settings/billing.html',
|
'users/settings/billing.html',
|
||||||
store_user=store_user, groups=groups, title='billing')
|
store_user=store_user, groups=groups, title='billing')
|
||||||
@ -237,3 +236,52 @@ def users_index():
|
|||||||
if not current_user.has_role('admin'):
|
if not current_user.has_role('admin'):
|
||||||
return abort(403)
|
return abort(403)
|
||||||
return render_template('users/index.html')
|
return render_template('users/index.html')
|
||||||
|
|
||||||
|
|
||||||
|
def user_roles_update(user_id):
|
||||||
|
api = system_util.pillar_api()
|
||||||
|
group_subscriber = Group.find_one({'where': {'name': 'subscriber'}}, api=api)
|
||||||
|
|
||||||
|
# Fetch the user once outside the loop, because we only need to get the
|
||||||
|
# subscription status once.
|
||||||
|
user = User.me(api=api)
|
||||||
|
|
||||||
|
store_user = subscriptions.fetch_user(user.email)
|
||||||
|
if store_user is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
max_retry = 5
|
||||||
|
for retry_count in range(max_retry):
|
||||||
|
# Update the user's role & groups for their subscription status.
|
||||||
|
roles = set(user.roles or [])
|
||||||
|
groups = set(user.groups or [])
|
||||||
|
|
||||||
|
if store_user['cloud_access'] == 1:
|
||||||
|
roles.add(u'subscriber')
|
||||||
|
groups.add(group_subscriber._id)
|
||||||
|
|
||||||
|
elif u'admin' not in roles:
|
||||||
|
roles.discard(u'subscriber')
|
||||||
|
groups.discard(group_subscriber._id)
|
||||||
|
|
||||||
|
# Only send an API request when the user has actually changed
|
||||||
|
if set(user.roles or []) == roles and set(user.groups or []) == groups:
|
||||||
|
break
|
||||||
|
|
||||||
|
user.roles = list(roles)
|
||||||
|
user.groups = list(groups)
|
||||||
|
|
||||||
|
try:
|
||||||
|
user.update(api=api)
|
||||||
|
except sdk_exceptions.PreconditionFailed:
|
||||||
|
log.warning('User etag changed while updating roles, retrying.')
|
||||||
|
else:
|
||||||
|
# Successful update, so we can stop the loop.
|
||||||
|
break
|
||||||
|
|
||||||
|
# Fetch the user for the next iteration.
|
||||||
|
if retry_count < max_retry - 1:
|
||||||
|
user = User.me(api=api)
|
||||||
|
else:
|
||||||
|
log.warning('Tried %i times to update user %s, and failed each time. Giving up.',
|
||||||
|
max_retry, user_id)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user