Merge branch 'master' of git.blender.org:pillar into elastic
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
import typing
|
||||
|
||||
import blinker
|
||||
from flask import Blueprint, Response
|
||||
import requests
|
||||
from requests.adapters import HTTPAdapter
|
||||
@@ -21,6 +22,10 @@ ROLES_BID_TO_PILLAR = {
|
||||
'cloud_has_subscription': 'has_subscription',
|
||||
}
|
||||
|
||||
user_subscription_updated = blinker.NamedSignal(
|
||||
'user_subscription_updated',
|
||||
'The sender is a UserClass instance, kwargs includes "revoke_roles" and "grant_roles".')
|
||||
|
||||
|
||||
@blueprint.route('/update-subscription')
|
||||
@authorization.require_login()
|
||||
@@ -31,7 +36,7 @@ def update_subscription() -> typing.Tuple[str, int]:
|
||||
"""
|
||||
|
||||
my_log: logging.Logger = log.getChild('update_subscription')
|
||||
current_user = auth.get_current_user()
|
||||
real_current_user = auth.get_current_user() # multiple accesses, just get unproxied.
|
||||
|
||||
try:
|
||||
bid_user = blender_id.fetch_blenderid_user()
|
||||
@@ -41,10 +46,10 @@ def update_subscription() -> typing.Tuple[str, int]:
|
||||
|
||||
if not bid_user:
|
||||
my_log.warning('Logged in user %s has no BlenderID account! '
|
||||
'Unable to update subscription status.', current_user.user_id)
|
||||
'Unable to update subscription status.', real_current_user.user_id)
|
||||
return '', 204
|
||||
|
||||
do_update_subscription(current_user, bid_user)
|
||||
do_update_subscription(real_current_user, bid_user)
|
||||
return '', 204
|
||||
|
||||
|
||||
@@ -157,6 +162,14 @@ def do_update_subscription(local_user: auth.UserClass, bid_user: dict):
|
||||
user_id, email, ', '.join(sorted(revoke_roles)))
|
||||
service.do_badger('revoke', roles=revoke_roles, user_id=user_id)
|
||||
|
||||
# Let the world know this user's subscription was updated.
|
||||
final_roles = (plr_roles - revoke_roles).union(grant_roles)
|
||||
local_user.roles = list(final_roles)
|
||||
local_user.collect_capabilities()
|
||||
user_subscription_updated.send(local_user,
|
||||
grant_roles=grant_roles,
|
||||
revoke_roles=revoke_roles)
|
||||
|
||||
# Re-index the user in the search database.
|
||||
from pillar.api.users import hooks
|
||||
hooks.push_updated_user_to_search({'_id': user_id}, {})
|
||||
|
@@ -376,6 +376,13 @@ class OrgManager:
|
||||
|
||||
return bool(org_count)
|
||||
|
||||
def user_is_unknown_member(self, member_email: str) -> bool:
|
||||
"""Return True iff the email is an unknown member of some org."""
|
||||
|
||||
org_coll = current_app.db('organizations')
|
||||
org_count = org_coll.count({'unknown_members': member_email})
|
||||
return bool(org_count)
|
||||
|
||||
|
||||
def setup_app(app):
|
||||
from . import patch, hooks
|
||||
|
@@ -2,7 +2,6 @@ import copy
|
||||
import logging
|
||||
|
||||
from flask import request, abort, current_app
|
||||
from gcloud import exceptions as gcs_exceptions
|
||||
|
||||
from pillar.api.node_types.asset import node_type_asset
|
||||
from pillar.api.node_types.comment import node_type_comment
|
||||
@@ -10,7 +9,6 @@ from pillar.api.node_types.group import node_type_group
|
||||
from pillar.api.node_types.group_texture import node_type_group_texture
|
||||
from pillar.api.node_types.texture import node_type_texture
|
||||
from pillar.api.file_storage_backends import default_storage_backend
|
||||
from pillar.api.file_storage_backends.gcs import GoogleCloudStorageBucket
|
||||
from pillar.api.utils import authorization, authentication
|
||||
from pillar.api.utils import remove_private_keys
|
||||
from pillar.api.utils.authorization import user_has_role, check_permissions
|
||||
|
@@ -198,8 +198,9 @@ def after_inserting_users(user_docs):
|
||||
user_email = user_doc.get('email')
|
||||
|
||||
if not user_id or not user_email:
|
||||
log.warning('User created with _id=%r and email=%r, unable to check organizations',
|
||||
user_id, user_email)
|
||||
# Missing emails can happen when creating a service account, it's fine.
|
||||
log.info('User created with _id=%r and email=%r, unable to check organizations',
|
||||
user_id, user_email)
|
||||
continue
|
||||
|
||||
om.make_member_known(user_id, user_email)
|
||||
|
@@ -69,19 +69,19 @@ def find_user_in_db(user_info: dict, provider='blender-id'):
|
||||
|
||||
users = current_app.data.driver.db['users']
|
||||
|
||||
user_id = user_info['id']
|
||||
query = {'$or': [
|
||||
{'auth': {'$elemMatch': {
|
||||
'user_id': str(user_info['id']),
|
||||
'user_id': str(user_id),
|
||||
'provider': provider}}},
|
||||
{'email': user_info['email']},
|
||||
]}
|
||||
]}
|
||||
log.debug('Querying: %s', query)
|
||||
db_user = users.find_one(query)
|
||||
|
||||
if db_user:
|
||||
log.debug('User with {provider} id {user_id} already in our database, '
|
||||
'updating with info from {provider}.'.format(
|
||||
provider=provider, user_id=user_info['id']))
|
||||
log.debug('User with %s id %s already in our database, updating with info from %s',
|
||||
provider, user_id, provider)
|
||||
db_user['email'] = user_info['email']
|
||||
|
||||
# Find out if an auth entry for the current provider already exists
|
||||
@@ -89,13 +89,13 @@ def find_user_in_db(user_info: dict, provider='blender-id'):
|
||||
if not provider_entry:
|
||||
db_user['auth'].append({
|
||||
'provider': provider,
|
||||
'user_id': str(user_info['id']),
|
||||
'user_id': str(user_id),
|
||||
'token': ''})
|
||||
else:
|
||||
log.debug('User %r not yet in our database, create a new one.', user_info['id'])
|
||||
log.debug('User %r not yet in our database, create a new one.', user_id)
|
||||
db_user = create_new_user_document(
|
||||
email=user_info['email'],
|
||||
user_id=user_info['id'],
|
||||
user_id=user_id,
|
||||
username=user_info['full_name'],
|
||||
provider=provider)
|
||||
db_user['username'] = make_unique_username(user_info['email'])
|
||||
@@ -118,9 +118,13 @@ def validate_token():
|
||||
|
||||
from pillar.auth import AnonymousUser
|
||||
|
||||
auth_header = request.headers.get('Authorization') or ''
|
||||
if request.authorization:
|
||||
token = request.authorization.username
|
||||
oauth_subclient = request.authorization.password
|
||||
elif auth_header.startswith('Bearer '):
|
||||
token = auth_header[7:].strip()
|
||||
oauth_subclient = ''
|
||||
else:
|
||||
# Check the session, the user might be logged in through Flask-Login.
|
||||
from pillar import auth
|
||||
@@ -180,7 +184,6 @@ def validate_this_token(token, oauth_subclient=None):
|
||||
def remove_token(token: str):
|
||||
"""Removes the token from the database."""
|
||||
|
||||
|
||||
tokens_coll = current_app.db('tokens')
|
||||
token_hashed = hash_auth_token(token)
|
||||
|
||||
@@ -261,13 +264,13 @@ def create_new_user(email, username, user_id):
|
||||
|
||||
|
||||
def create_new_user_document(email, user_id, username, provider='blender-id',
|
||||
token=''):
|
||||
token='', *, full_name=''):
|
||||
"""Creates a new user document, without storing it in MongoDB. The token
|
||||
parameter is a password in case provider is "local".
|
||||
"""
|
||||
|
||||
user_data = {
|
||||
'full_name': username,
|
||||
'full_name': full_name or username,
|
||||
'username': username,
|
||||
'email': email,
|
||||
'auth': [{
|
||||
@@ -371,6 +374,10 @@ def upsert_user(db_user):
|
||||
raise wz_exceptions.InternalServerError(
|
||||
'Non-ObjectID string found in user.groups: %s' % db_user)
|
||||
|
||||
if not db_user['full_name']:
|
||||
# Blender ID doesn't need a full name, but we do.
|
||||
db_user['full_name'] = db_user['username']
|
||||
|
||||
r = {}
|
||||
for retry in range(5):
|
||||
if '_id' in db_user:
|
||||
|
Reference in New Issue
Block a user