diff --git a/allianceauth/__init__.py b/allianceauth/__init__.py index 81b01c5d..96dfd8bb 100644 --- a/allianceauth/__init__.py +++ b/allianceauth/__init__.py @@ -1,7 +1,7 @@ # This will make sure the app is always imported when # Django starts so that shared_task will use this app. -__version__ = '2.9.0a2' +__version__ = '2.9.0a3' __title__ = 'Alliance Auth' __url__ = 'https://gitlab.com/allianceauth/allianceauth' NAME = '%s v%s' % (__title__, __version__) diff --git a/allianceauth/services/modules/discord/managers.py b/allianceauth/services/modules/discord/managers.py index e8953586..7945ab6b 100644 --- a/allianceauth/services/modules/discord/managers.py +++ b/allianceauth/services/modules/discord/managers.py @@ -83,10 +83,31 @@ class DiscordUserManager(models.Manager): if created is not False: if created is None: logger.debug( - "User %s with Discord ID %s is already a member.", + "User %s with Discord ID %s is already a member. Forcing a Refresh", user, user_id, ) + + # Force an update cause the discord API won't do it for us. + if role_ids: + role_ids = list(role_ids) + + updated = bot_client.modify_guild_member( + guild_id=DISCORD_GUILD_ID, + user_id=user_id, + role_ids=role_ids, + nick=nickname + ) + + if not updated: + # Could not update the new user so fail. + logger.warning( + "Failed to add user %s with Discord ID %s to Discord server", + user, + user_id, + ) + return False + self.update_or_create( user=user, defaults={ diff --git a/allianceauth/services/modules/discord/tests/test_managers.py b/allianceauth/services/modules/discord/tests/test_managers.py index 62f110e0..b2ed0d8e 100644 --- a/allianceauth/services/modules/discord/tests/test_managers.py +++ b/allianceauth/services/modules/discord/tests/test_managers.py @@ -111,6 +111,40 @@ class TestAddUser(TestCase): self.assertSetEqual(set(kwargs['role_ids']), {1, 2, 3}) self.assertIsNone(kwargs['nick']) + def test_can_activate_existing_user_with_roles_no_nick( + self, + mock_user_formatted_nick, + mock_user_group_names, + mock_exchange_auth_code_for_token, + mock_DiscordClient + ): + roles = [ + create_matched_role(ROLE_ALPHA), + create_matched_role(ROLE_BRAVO), + create_matched_role(ROLE_CHARLIE) + ] + mock_user_formatted_nick.return_value = None + mock_user_group_names.return_value = ['a', 'b', 'c'] + mock_exchange_auth_code_for_token.return_value = self.access_token + mock_DiscordClient.return_value.current_user.return_value = self.user_info + mock_DiscordClient.return_value.match_or_create_roles_from_names\ + .return_value = roles + mock_DiscordClient.return_value.add_guild_member.return_value = None + mock_DiscordClient.return_value.modify_guild_member.return_value = True + + result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef') + self.assertTrue(result) + self.assertTrue( + DiscordUser.objects.filter(user=self.user, uid=TEST_USER_ID).exists() + ) + self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called) + self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called) + args, kwargs = mock_DiscordClient.return_value.modify_guild_member.call_args + self.assertEqual(kwargs['guild_id'], TEST_GUILD_ID) + self.assertEqual(kwargs['user_id'], TEST_USER_ID) + self.assertSetEqual(set(kwargs['role_ids']), {1, 2, 3}) + self.assertIsNone(kwargs['nick']) + @patch(MODULE_PATH + '.managers.DISCORD_SYNC_NAMES', True) def test_can_create_user_no_roles_with_nick( self, @@ -140,6 +174,36 @@ class TestAddUser(TestCase): self.assertIsNone(kwargs['role_ids']) self.assertEqual(kwargs['nick'], TEST_MAIN_NAME) + @patch(MODULE_PATH + '.managers.DISCORD_SYNC_NAMES', True) + def test_can_activate_existing_user_no_roles_with_nick( + self, + mock_user_formatted_nick, + mock_user_group_names, + mock_exchange_auth_code_for_token, + mock_DiscordClient + ): + mock_user_formatted_nick.return_value = TEST_MAIN_NAME + mock_user_group_names.return_value = [] + mock_exchange_auth_code_for_token.return_value = self.access_token + mock_DiscordClient.return_value.current_user.return_value = self.user_info + mock_DiscordClient.return_value.match_or_create_roles_from_names\ + .return_value = [] + mock_DiscordClient.return_value.add_guild_member.return_value = None + mock_DiscordClient.return_value.modify_guild_member.return_value = True + + result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef') + self.assertTrue(result) + self.assertTrue( + DiscordUser.objects.filter(user=self.user, uid=TEST_USER_ID).exists() + ) + self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called) + self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called) + args, kwargs = mock_DiscordClient.return_value.modify_guild_member.call_args + self.assertEqual(kwargs['guild_id'], TEST_GUILD_ID) + self.assertEqual(kwargs['user_id'], TEST_USER_ID) + self.assertIsNone(kwargs['role_ids']) + self.assertEqual(kwargs['nick'], TEST_MAIN_NAME) + @patch(MODULE_PATH + '.managers.DISCORD_SYNC_NAMES', False) def test_can_create_user_no_roles_and_without_nick_if_turned_off( self, @@ -183,6 +247,7 @@ class TestAddUser(TestCase): mock_DiscordClient.return_value.match_or_create_roles_from_names\ .return_value = [] mock_DiscordClient.return_value.add_guild_member.return_value = None + mock_DiscordClient.return_value.modify_guild_member.return_value = True result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef') self.assertTrue(result) @@ -190,6 +255,31 @@ class TestAddUser(TestCase): DiscordUser.objects.filter(user=self.user, uid=TEST_USER_ID).exists() ) self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called) + self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called) + + def test_can_activate_existing_guild_member_failure( + self, + mock_user_formatted_nick, + mock_user_group_names, + mock_exchange_auth_code_for_token, + mock_DiscordClient + ): + mock_user_formatted_nick.return_value = None + mock_user_group_names.return_value = [] + mock_exchange_auth_code_for_token.return_value = self.access_token + mock_DiscordClient.return_value.current_user.return_value = self.user_info + mock_DiscordClient.return_value.match_or_create_roles_from_names\ + .return_value = [] + mock_DiscordClient.return_value.add_guild_member.return_value = None + mock_DiscordClient.return_value.modify_guild_member.return_value = False + + result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef') + self.assertFalse(result) + self.assertFalse( + DiscordUser.objects.filter(user=self.user, uid=TEST_USER_ID).exists() + ) + self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called) + self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called) def test_return_false_when_user_creation_fails( self, diff --git a/allianceauth/templates/allianceauth/messages.html b/allianceauth/templates/allianceauth/messages.html index 38a01104..e1c61455 100644 --- a/allianceauth/templates/allianceauth/messages.html +++ b/allianceauth/templates/allianceauth/messages.html @@ -5,16 +5,22 @@ - {% if message.level_tag == "info" %} - - {% elif message.level_tag == "success" %} - - {% elif message.level_tag == "warning" %} - - {% elif message.level_tag == "danger" %} - - {% endif %} -  {{ message }} + +
+ {% if message.level_tag == "info" %} + + {% elif message.level_tag == "success" %} + + {% elif message.level_tag == "warning" %} + + {% elif message.level_tag == "danger" %} + + {% endif %} +
+ +
+ {{ message }} +
{% endfor %} {% endif %}