Check subscription status on login.
This commit is contained in:
parent
dcbefc33ae
commit
07691db874
@ -64,7 +64,7 @@ class PillarServer(Eve):
|
||||
self.load_config()
|
||||
|
||||
# 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._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 collections import defaultdict
|
||||
|
||||
import requests.certs
|
||||
|
||||
RFC1123_DATE_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
|
||||
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'
|
||||
|
||||
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)
|
||||
from flask_login import login_required, login_user, logout_user, current_user
|
||||
from flask_oauthlib.client import OAuthException
|
||||
from pillar.auth import UserClass
|
||||
from pillar.auth import UserClass, subscriptions
|
||||
from pillar.web import system_util
|
||||
from .forms import UserProfileForm
|
||||
from .forms import UserSettingsEmailsForm
|
||||
@ -55,13 +55,12 @@ def blender_id_authorized():
|
||||
|
||||
user = UserClass(oauth_resp['access_token'])
|
||||
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:
|
||||
pass
|
||||
if current_user is not None:
|
||||
# Check with the store for user roles. If the user has an active
|
||||
# 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')
|
||||
if next_after_login:
|
||||
@ -179,9 +178,9 @@ def settings_billing():
|
||||
for group_id in user.groups:
|
||||
group = Group.find(group_id, api=api)
|
||||
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 = r.json()
|
||||
|
||||
store_user = subscriptions.fetch_user(user.email)
|
||||
|
||||
return render_template(
|
||||
'users/settings/billing.html',
|
||||
store_user=store_user, groups=groups, title='billing')
|
||||
@ -237,3 +236,52 @@ def users_index():
|
||||
if not current_user.has_role('admin'):
|
||||
return abort(403)
|
||||
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