Send a Blinker signal when someone's subscription status changes

This is very close to the 'roles changed' signal, with the difference that
it is sent only once for multiple role changes.
This commit is contained in:
Sybren A. Stüvel 2017-12-21 12:59:32 +01:00
parent ef1609efc2
commit 01f81ce4d5
2 changed files with 41 additions and 2 deletions

View File

@ -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()
@ -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_algolia({'_id': user_id}, {})

View File

@ -17,6 +17,13 @@ class RoleUpdatingTest(AbstractPillarTest):
with self.app.test_request_context():
self.create_standard_groups()
from pillar.api.blender_cloud import subscription as sub
self.user_subs_signal_calls = []
sub.user_subscription_updated.connect(self._user_subs_signal)
def _user_subs_signal(self, sender, **kwargs):
self.user_subs_signal_calls.append((sender, kwargs))
def _setup_testcase(self, mocked_fetch_blenderid_user, *,
bid_roles: typing.Set[str]):
import urllib.parse
@ -54,6 +61,12 @@ class RoleUpdatingTest(AbstractPillarTest):
user_info = self.get('/api/users/me', auth_token='my-happy-token').json()
self.assertEqual({'subscriber', 'has_subscription'}, set(user_info['roles']))
# Check the signals
self.assertEqual(1, len(self.user_subs_signal_calls))
sender, kwargs = self.user_subs_signal_calls[0]
self.assertEqual({'revoke_roles': set(), 'grant_roles': {'subscriber', 'has_subscription'}},
kwargs)
@responses.activate
@mock.patch('pillar.api.blender_id.fetch_blenderid_user')
def test_store_api_role_revoke_subscriber(self, mocked_fetch_blenderid_user):
@ -61,9 +74,9 @@ class RoleUpdatingTest(AbstractPillarTest):
bid_roles={'conference_speaker'})
# Make sure this user is currently known as a subcriber.
self.create_user(roles={'subscriber'}, token='my-happy-token')
self.create_user(roles={'subscriber', 'has_subscription'}, token='my-happy-token')
user_info = self.get('/api/users/me', auth_token='my-happy-token').json()
self.assertEqual(['subscriber'], user_info['roles'])
self.assertEqual({'subscriber', 'has_subscription'}, set(user_info['roles']))
# And after updating, it shouldn't be.
self.get('/api/bcloud/update-subscription', auth_token='my-happy-token',
@ -71,6 +84,11 @@ class RoleUpdatingTest(AbstractPillarTest):
user_info = self.get('/api/users/me', auth_token='my-happy-token').json()
self.assertEqual([], user_info['roles'])
self.assertEqual(1, len(self.user_subs_signal_calls))
sender, kwargs = self.user_subs_signal_calls[0]
self.assertEqual({'revoke_roles': {'subscriber', 'has_subscription'}, 'grant_roles': set()},
kwargs)
@responses.activate
@mock.patch('pillar.api.blender_id.fetch_blenderid_user')
def test_bid_api_grant_demo(self, mocked_fetch_blenderid_user):
@ -83,6 +101,10 @@ class RoleUpdatingTest(AbstractPillarTest):
user_info = self.get('/api/users/me', auth_token='my-happy-token').json()
self.assertEqual(['demo'], user_info['roles'])
self.assertEqual(1, len(self.user_subs_signal_calls))
sender, kwargs = self.user_subs_signal_calls[0]
self.assertEqual({'revoke_roles': set(), 'grant_roles': {'demo'}}, kwargs)
@responses.activate
@mock.patch('pillar.api.blender_id.fetch_blenderid_user')
def test_bid_api_role_revoke_demo(self, mocked_fetch_blenderid_user):
@ -99,3 +121,7 @@ class RoleUpdatingTest(AbstractPillarTest):
expected_status=204)
user_info = self.get('/api/users/me', auth_token='my-happy-token').json()
self.assertEqual([], user_info['roles'])
self.assertEqual(1, len(self.user_subs_signal_calls))
sender, kwargs = self.user_subs_signal_calls[0]
self.assertEqual({'revoke_roles': {'demo'}, 'grant_roles': set()}, kwargs)