Added "Update from Blender ID" button
Added this button in the /u/ user/embed view, so that admins can easily force a re-check from Blender ID without requiring the user themselves to perform any actions.
This commit is contained in:
parent
c8221ea0e4
commit
87fe1887e8
@ -1,11 +1,14 @@
|
||||
import collections
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from flask import Blueprint
|
||||
from flask import Blueprint, Response
|
||||
import requests
|
||||
from requests.adapters import HTTPAdapter
|
||||
|
||||
from pillar.auth import UserClass
|
||||
from pillar.api.utils import authorization
|
||||
from pillar import auth, current_app
|
||||
from pillar.api import blender_id
|
||||
from pillar.api.utils import authorization, jsonify
|
||||
from pillar.auth import current_user
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
blueprint = Blueprint('blender_cloud.subscription', __name__)
|
||||
@ -27,9 +30,6 @@ def update_subscription() -> typing.Tuple[str, int]:
|
||||
Returns an empty HTTP response.
|
||||
"""
|
||||
|
||||
from pillar import auth
|
||||
from pillar.api import blender_id
|
||||
|
||||
my_log: logging.Logger = log.getChild('update_subscription')
|
||||
current_user = auth.get_current_user()
|
||||
|
||||
@ -48,7 +48,58 @@ def update_subscription() -> typing.Tuple[str, int]:
|
||||
return '', 204
|
||||
|
||||
|
||||
def do_update_subscription(local_user: UserClass, bid_user: dict):
|
||||
@blueprint.route('/update-subscription-for/<user_id>', methods=['POST'])
|
||||
@authorization.require_login(require_cap='admin')
|
||||
def update_subscription_for(user_id: str):
|
||||
"""Updates the user based on their info at Blender ID."""
|
||||
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from pillar.api.utils import str2id
|
||||
|
||||
my_log = log.getChild('update_subscription_for')
|
||||
|
||||
bid_session = requests.Session()
|
||||
bid_session.mount('https://', HTTPAdapter(max_retries=5))
|
||||
bid_session.mount('http://', HTTPAdapter(max_retries=5))
|
||||
|
||||
users_coll = current_app.db('users')
|
||||
db_user = users_coll.find_one({'_id': str2id(user_id)})
|
||||
if not db_user:
|
||||
my_log.warning('User %s not found in database', user_id)
|
||||
return Response(f'User {user_id} not found in our database', status=404)
|
||||
|
||||
log.info('Updating user %s from Blender ID on behalf of %s',
|
||||
db_user['email'], current_user.email)
|
||||
|
||||
bid_user_id = blender_id.get_user_blenderid(db_user)
|
||||
if not bid_user_id:
|
||||
my_log.info('User %s has no Blender ID', user_id)
|
||||
return Response('User has no Blender ID', status=404)
|
||||
|
||||
# Get the user info from Blender ID, and handle errors.
|
||||
api_url = current_app.config['BLENDER_ID_USER_INFO_API']
|
||||
api_token = current_app.config['BLENDER_ID_USER_INFO_TOKEN']
|
||||
url = urljoin(api_url, bid_user_id)
|
||||
resp = bid_session.get(url, headers={'Authorization': f'Bearer {api_token}'})
|
||||
if resp.status_code == 404:
|
||||
my_log.info('User %s has a Blender ID %s but Blender ID itself does not find it',
|
||||
user_id, bid_user_id)
|
||||
return Response(f'User {bid_user_id} does not exist at Blender ID', status=404)
|
||||
if resp.status_code != 200:
|
||||
my_log.info('Error code %s getting user %s from Blender ID (resp = %s)',
|
||||
resp.status_code, user_id, resp.text)
|
||||
return Response(f'Error code {resp.status_code} from Blender ID', status=resp.status_code)
|
||||
|
||||
# Update the user in our database.
|
||||
local_user = auth.UserClass.construct('', db_user)
|
||||
bid_user = resp.json()
|
||||
do_update_subscription(local_user, bid_user)
|
||||
|
||||
return '', 204
|
||||
|
||||
|
||||
def do_update_subscription(local_user: auth.UserClass, bid_user: dict):
|
||||
"""Updates the subscription status of the user given the Blender ID user info.
|
||||
|
||||
Uses the badger service to update the user's roles from Blender ID.
|
||||
@ -106,6 +157,10 @@ def do_update_subscription(local_user: UserClass, bid_user: dict):
|
||||
user_id, email, ', '.join(sorted(revoke_roles)))
|
||||
service.do_badger('revoke', roles=revoke_roles, user_id=user_id)
|
||||
|
||||
# Re-index the user in the search database.
|
||||
from pillar.api.users import hooks
|
||||
hooks.push_updated_user_to_algolia({'_id': user_id}, {})
|
||||
|
||||
|
||||
def setup_app(app, url_prefix):
|
||||
log.info('Registering blueprint at %s', url_prefix)
|
||||
|
@ -168,6 +168,24 @@ def _compute_token_expiry(token_expires_string):
|
||||
return min(blid_expiry, our_expiry)
|
||||
|
||||
|
||||
def get_user_blenderid(db_user: dict) -> str:
|
||||
"""Returns the Blender ID user ID for this Pillar user.
|
||||
|
||||
Takes the string from 'auth.*.user_id' for the '*' where 'provider'
|
||||
is 'blender-id'.
|
||||
|
||||
:returns the user ID, or the empty string when the user has none.
|
||||
"""
|
||||
|
||||
bid_user_ids = [auth['user_id']
|
||||
for auth in db_user['auth']
|
||||
if auth['provider'] == 'blender-id']
|
||||
try:
|
||||
return bid_user_ids[0]
|
||||
except IndexError:
|
||||
return ''
|
||||
|
||||
|
||||
def fetch_blenderid_user() -> dict:
|
||||
"""Returns the user info of the currently logged in user from BlenderID.
|
||||
|
||||
|
@ -99,8 +99,9 @@ FULL_FILE_ACCESS_ROLES = {'admin', 'subscriber', 'demo'}
|
||||
BLENDER_ID_CLIENT_ID = 'SPECIAL-SNOWFLAKE-57'
|
||||
BLENDER_ID_SUBCLIENT_ID = 'PILLAR'
|
||||
|
||||
# Blender ID user info API endpoint URL and auth token, only used for
|
||||
# reconciling subscribers. The token requires the 'userinfo' scope.
|
||||
# Blender ID user info API endpoint URL and auth token, used for
|
||||
# reconciling subscribers and updating their info from /u/.
|
||||
# The token requires the 'userinfo' scope.
|
||||
BLENDER_ID_USER_INFO_API = 'http://blender-id:8000/api/user/'
|
||||
BLENDER_ID_USER_INFO_TOKEN = '-set-in-config-local-'
|
||||
|
||||
|
@ -72,6 +72,7 @@
|
||||
| none
|
||||
| {% endif %}
|
||||
|
||||
a.btn.btn-default(href="javascript:update_from_bid()") Update from Blender ID
|
||||
a.btn.btn-default(href="javascript:$('#user-edit-container').html('')") Cancel
|
||||
|
||||
input#submit_edit_user.btn.btn-default(
|
||||
@ -103,4 +104,16 @@ script(type="text/javascript").
|
||||
|
||||
new Clipboard('.copy-to-clipboard');
|
||||
|
||||
function update_from_bid() {
|
||||
var url = '{{ url_for("blender_cloud.subscription.update_subscription_for", user_id=user.user_id) }}';
|
||||
$.post(url)
|
||||
.done(function(data) {
|
||||
toastr.info('User updated from Blender ID');
|
||||
displayUser('{{ user.user_id }}');
|
||||
})
|
||||
.fail(function(data) {
|
||||
toastr.error(data.responseText);
|
||||
});
|
||||
}
|
||||
|
||||
| {% endblock %}
|
||||
|
Loading…
x
Reference in New Issue
Block a user