示例#1
0
def update_subscription():
    """Updates the subscription status of the current user.

    Returns an empty HTTP response.
    """

    import pprint
    from pillar.api import blender_id, service
    from pillar.api.utils import authentication

    my_log: logging.Logger = log.getChild('update_subscription')
    user_id = authentication.current_user_id()

    bid_user = blender_id.fetch_blenderid_user()
    if not bid_user:
        my_log.warning(
            'Logged in user %s has no BlenderID account! '
            'Unable to update subscription status.', user_id)
        return '', 204

    # Use the Blender ID email address to check with the store. At least that reduces the
    # number of email addresses that could be out of sync to two (rather than three when we
    # use the email address from our local database).
    try:
        email = bid_user['email']
    except KeyError:
        my_log.error(
            'Blender ID response did not include an email address, '
            'unable to update subscription status: %s',
            pprint.pformat(bid_user, compact=True))
        return 'Internal error', 500
    store_user = fetch_subscription_info(email) or {}

    # Handle the role changes via the badger service functionality.
    grant_subscriber = store_user.get('cloud_access', 0) == 1
    grant_demo = bid_user.get('roles', {}).get('cloud_demo', False)

    is_subscriber = authorization.user_has_role('subscriber')
    is_demo = authorization.user_has_role('demo')

    if grant_subscriber != is_subscriber:
        action = 'grant' if grant_subscriber else 'revoke'
        my_log.info('%sing subscriber role to user %s (Blender ID email %s)',
                    action, user_id, email)
        service.do_badger(action, role='subscriber', user_id=user_id)
    else:
        my_log.debug('Not changing subscriber role, grant=%r and is=%s',
                     grant_subscriber, is_subscriber)

    if grant_demo != is_demo:
        action = 'grant' if grant_demo else 'revoke'
        my_log.info('%sing demo role to user %s (Blender ID email %s)', action,
                    user_id, email)
        service.do_badger(action, role='demo', user_id=user_id)
    else:
        my_log.debug('Not changing demo role, grant=%r and is=%s', grant_demo,
                     is_demo)

    return '', 204
示例#2
0
def revoke_admin(user_email):
    """Revokes the user's flamenco-admin role."""

    from pillar.api.service import do_badger

    _, status = do_badger('revoke', role='flamenco-admin', user_email=user_email)
    if status != 204:
        log.error('Unable to find user %s', user_email)
        return 1

    log.info('Done.')
    return 0
示例#3
0
def revoke_admin(user_email):
    """Revokes the user's flamenco-admin role."""

    from pillar.api.service import do_badger

    _, status = do_badger('revoke', role='flamenco-admin', user_email=user_email)
    if status != 204:
        log.error('Unable to find user %s', user_email)
        return 1

    log.info('Done.')
    return 0
示例#4
0
def badger(action, user_email, role):
    from pillar.api import service

    with current_app.app_context():
        service.fetch_role_to_group_id_map()
        response, status = service.do_badger(action,
                                             role=role,
                                             user_email=user_email)

    if status == 204:
        log.info('Done.')
    else:
        log.info('Response: %s', response)
        log.info('Status  : %i', status)
示例#5
0
    def refresh_roles(self, user_id: bson.ObjectId) -> typing.Set[str]:
        """Refreshes the user's roles to own roles + organizations' roles.

        :returns: the applied set of roles.
        """

        assert isinstance(user_id, bson.ObjectId)

        from pillar.api.service import do_badger

        self._log.info('Refreshing roles for user %s', user_id)

        org_coll = current_app.db('organizations')
        tokens_coll = current_app.db('tokens')

        def aggr_roles(coll, match: dict) -> typing.Set[str]:
            query = coll.aggregate([{
                '$match': match
            }, {
                '$project': {
                    'org_roles': 1
                }
            }, {
                '$unwind': {
                    'path': '$org_roles'
                }
            }, {
                '$group': {
                    '_id': None,
                    'org_roles': {
                        '$addToSet': '$org_roles'
                    },
                }
            }])

            # If the user has no organizations/tokens at all, the query will have no results.
            try:
                org_roles_doc = query.next()
            except StopIteration:
                return set()
            return set(org_roles_doc['org_roles'])

        # Join all organization-given roles and roles from the tokens collection.
        org_roles = aggr_roles(org_coll, {'members': user_id})
        self._log.debug('Organization-given roles for user %s: %s', user_id,
                        org_roles)
        token_roles = aggr_roles(tokens_coll, {
            'user': user_id,
            'expire_time': {
                "$gt": utcnow()
            },
        })
        self._log.debug('Token-given roles for user %s: %s', user_id,
                        token_roles)
        org_roles.update(token_roles)

        users_coll = current_app.db('users')
        user_doc = users_coll.find_one(user_id, projection={'roles': 1})
        if not user_doc:
            self._log.warning(
                'Trying refresh roles of non-existing user %s, ignoring',
                user_id)
            return set()

        all_user_roles = set(user_doc.get('roles') or [])
        existing_org_roles = {
            role
            for role in all_user_roles if role.startswith('org-')
        }

        grant_roles = org_roles - all_user_roles
        revoke_roles = existing_org_roles - org_roles

        if grant_roles:
            do_badger('grant', roles=grant_roles, user_id=user_id)
        if revoke_roles:
            do_badger('revoke', roles=revoke_roles, user_id=user_id)

        return all_user_roles.union(grant_roles) - revoke_roles
示例#6
0
    def refresh_roles(self, user_id: bson.ObjectId):
        """Refreshes the user's roles to own roles + organizations' roles."""

        assert isinstance(user_id, bson.ObjectId)

        from pillar.api.service import do_badger

        self._log.info('Refreshing roles for user %s', user_id)

        org_coll = current_app.db('organizations')

        # Aggregate all org-given roles for this user.
        query = org_coll.aggregate([{
            '$match': {
                'members': user_id
            }
        }, {
            '$project': {
                'org_roles': 1
            }
        }, {
            '$unwind': {
                'path': '$org_roles'
            }
        }, {
            '$group': {
                '_id': None,
                'org_roles': {
                    '$addToSet': '$org_roles'
                },
            }
        }])

        # If the user has no organizations at all, the query will have no results.
        try:
            org_roles_doc = query.next()
        except StopIteration:
            org_roles = set()
        else:
            org_roles = set(org_roles_doc['org_roles'])

        users_coll = current_app.db('users')
        user_doc = users_coll.find_one(user_id, projection={'roles': 1})
        if not user_doc:
            self._log.warning(
                'Trying refresh roles of non-existing user %s, ignoring',
                user_id)
            return

        all_user_roles = set(user_doc.get('roles') or [])
        existing_org_roles = {
            role
            for role in all_user_roles if role.startswith('org-')
        }

        grant_roles = org_roles - all_user_roles
        revoke_roles = existing_org_roles - org_roles

        if grant_roles:
            do_badger('grant', roles=grant_roles, user_id=user_id)
        if revoke_roles:
            do_badger('revoke', roles=revoke_roles, user_id=user_id)