Repository: softlayer/softlayer-python
Pull request #1297 (2020-07-11 02:23:35)

Notification management


Patch:
diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py
index 48b0af83..049b43c3 100644
--- a/SoftLayer/CLI/routes.py
+++ b/SoftLayer/CLI/routes.py
@@ -316,6 +316,8 @@
     ('user:detail', 'SoftLayer.CLI.user.detail:cli'),
     ('user:permissions', 'SoftLayer.CLI.user.permissions:cli'),
     ('user:edit-permissions', 'SoftLayer.CLI.user.edit_permissions:cli'),
+    ('user:notifications', 'SoftLayer.CLI.user.notifications:cli'),
+    ('user:edit-notifications', 'SoftLayer.CLI.user.edit_notifications:cli'),
     ('user:edit-details', 'SoftLayer.CLI.user.edit_details:cli'),
     ('user:create', 'SoftLayer.CLI.user.create:cli'),
     ('user:delete', 'SoftLayer.CLI.user.delete:cli'),
diff --git a/SoftLayer/CLI/user/edit_notifications.py b/SoftLayer/CLI/user/edit_notifications.py
new file mode 100644
index 00000000..1be7527c
--- /dev/null
+++ b/SoftLayer/CLI/user/edit_notifications.py
@@ -0,0 +1,35 @@
+"""Enable or Disable specific noticication for the current user"""
+# :license: MIT, see LICENSE for more details.
+
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+
+
+@click.command()
+@click.option('--enable/--disable', default=True,
+              help="Enable (DEFAULT) or Disable selected notification")
+@click.argument('notification', nargs=-1, required=True)
+@environment.pass_env
+def cli(env, enable, notification):
+    """Enable or Disable specific notifications for the active user.
+
+    Notification names should be enclosed in quotation marks.
+    Example::
+
+        slcli user edit-notifications --enable 'Order Approved' 'Reload Complete'
+
+    """
+
+    mgr = SoftLayer.UserManager(env.client)
+
+    if enable:
+        result = mgr.enable_notifications(notification)
+    else:
+        result = mgr.disable_notifications(notification)
+
+    if result:
+        click.secho("Notifications updated successfully: %s" % ", ".join(notification), fg='green')
+    else:
+        click.secho("Failed to update notifications: %s" % ", ".join(notification), fg='red')
diff --git a/SoftLayer/CLI/user/notifications.py b/SoftLayer/CLI/user/notifications.py
new file mode 100644
index 00000000..deffd951
--- /dev/null
+++ b/SoftLayer/CLI/user/notifications.py
@@ -0,0 +1,34 @@
+"""List user notifications"""
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import formatting
+
+
+@click.command()
+@environment.pass_env
+def cli(env):
+    """My Notifications."""
+
+    mgr = SoftLayer.UserManager(env.client)
+
+    all_notifications = mgr.get_all_notifications()
+
+    env.fout(notification_table(all_notifications))
+
+
+def notification_table(all_notifications):
+    """Creates a table of available notifications"""
+
+    table = formatting.Table(['Id', 'Name', 'Description', 'Enabled'])
+    table.align['Id'] = 'l'
+    table.align['Name'] = 'l'
+    table.align['Description'] = 'l'
+    table.align['Enabled'] = 'l'
+    for notification in all_notifications:
+        table.add_row([notification['id'],
+                       notification['name'],
+                       notification['description'],
+                       notification['enabled']])
+    return table
diff --git a/SoftLayer/fixtures/SoftLayer_Email_Subscription.py b/SoftLayer/fixtures/SoftLayer_Email_Subscription.py
new file mode 100644
index 00000000..bc3104b1
--- /dev/null
+++ b/SoftLayer/fixtures/SoftLayer_Email_Subscription.py
@@ -0,0 +1,22 @@
+getAllObjects = [
+    {'description': 'Email about your order.',
+     'enabled': True,
+     'id': 1,
+     'name': 'Order Being Reviewed'
+     },
+    {'description': 'Maintenances that will or are likely to cause service '
+                    'outages and disruptions',
+     'enabled': True,
+     'id': 8,
+     'name': 'High Impact'
+     },
+    {'description': 'Testing description.',
+     'enabled': True,
+     'id': 111,
+     'name': 'Test notification'
+     }
+]
+
+enable = True
+
+disable = True
diff --git a/SoftLayer/managers/user.py b/SoftLayer/managers/user.py
index 5875d76a..0948df8b 100644
--- a/SoftLayer/managers/user.py
+++ b/SoftLayer/managers/user.py
@@ -36,6 +36,7 @@ def __init__(self, client):
         self.user_service = self.client['SoftLayer_User_Customer']
         self.override_service = self.client['Network_Service_Vpn_Overrides']
         self.account_service = self.client['SoftLayer_Account']
+        self.subscription_service = self.client['SoftLayer_Email_Subscription']
         self.resolvers = [self._get_id_from_username]
         self.all_permissions = None
 
@@ -85,6 +86,52 @@ def get_all_permissions(self):
             self.all_permissions = sorted(permissions, key=itemgetter('keyName'))
         return self.all_permissions
 
+    def get_all_notifications(self):
+        """Calls SoftLayer_Email_Subscription::getAllObjects
+
+        Stores the result in self.all_permissions
+        :returns: A list of dictionaries that contains all valid permissions
+        """
+        return self.subscription_service.getAllObjects(mask='mask[enabled]')
+
+    def enable_notifications(self, notifications_names):
+        """Enables a list of notifications for the current a user profile.
+
+        :param list notifications_names: List of notifications names to enable
+        :returns: True on success
+
+        Example::
+            enable_notifications(['Order Approved','Reload Complete'])
+        """
+
+        result = False
+        notifications = self.gather_notifications(notifications_names)
+        for notification in notifications:
+            notification_id = notification.get('id')
+            result = self.subscription_service.enable(id=notification_id)
+            if not result:
+                return False
+        return result
+
+    def disable_notifications(self, notifications_names):
+        """Disable a list of notifications for the current a user profile.
+
+        :param list notifications_names: List of notifications names to disable
+        :returns: True on success
+
+        Example::
+            disable_notifications(['Order Approved','Reload Complete'])
+        """
+
+        result = False
+        notifications = self.gather_notifications(notifications_names)
+        for notification in notifications:
+            notification_id = notification.get('id')
+            result = self.subscription_service.disable(id=notification_id)
+            if not result:
+                return False
+        return result
+
     def add_permissions(self, user_id, permissions):
         """Enables a list of permissions for a user
 
@@ -237,6 +284,23 @@ def format_permission_object(self, permissions):
                 raise exceptions.SoftLayerError("'%s' is not a valid permission" % permission)
         return pretty_permissions
 
+    def gather_notifications(self, notifications_names):
+        """Gets a list of notifications.
+
+        :param list notifications_names: A list of notifications names.
+        :returns: list of notifications.
+        """
+        notifications = []
+        available_notifications = self.get_all_notifications()
+        for notification in notifications_names:
+            result = next((item for item in available_notifications
+                           if item.get('name') == notification), None)
+            if result:
+                notifications.append(result)
+            else:
+                raise exceptions.SoftLayerError("{} is not a valid notification name".format(notification))
+        return notifications
+
     def create_user(self, user_object, password):
         """Blindly sends user_object to SoftLayer_User_Customer::createObject
 
diff --git a/docs/cli/users.rst b/docs/cli/users.rst
index feb94e35..5195a778 100644
--- a/docs/cli/users.rst
+++ b/docs/cli/users.rst
@@ -12,10 +12,18 @@ Version 5.6.0 introduces the ability to interact with user accounts from the cli
     :prog: user detail
     :show-nested:
 
+.. click:: SoftLayer.CLI.user.notifications:cli
+    :prog: user notifications
+    :show-nested:
+
 .. click:: SoftLayer.CLI.user.permissions:cli
     :prog: user permissions
     :show-nested:
 
+.. click:: SoftLayer.CLI.user.edit_notifications:cli
+    :prog: user edit-notifications
+    :show-nested:
+
 .. click:: SoftLayer.CLI.user.edit_permissions:cli
     :prog: user edit-permissions
     :show-nested:


Test patch:
diff --git a/tests/CLI/modules/user_tests.py b/tests/CLI/modules/user_tests.py
index 6f58c14a..f16ef184 100644
--- a/tests/CLI/modules/user_tests.py
+++ b/tests/CLI/modules/user_tests.py
@@ -305,3 +305,35 @@ def test_vpn_subnet_remove(self, click):
         result = self.run_command(['user', 'vpn-subnet', '12345', '--remove', '1234'])
         click.secho.assert_called_with('12345 updated successfully', fg='green')
         self.assert_no_fail(result)
+
+    """User notification tests"""
+
+    def test_notificacions_list(self):
+        result = self.run_command(['user', 'notifications'])
+        self.assert_no_fail(result)
+        self.assert_called_with('SoftLayer_Email_Subscription', 'getAllObjects', mask='mask[enabled]')
+
+    """User edit-notification tests"""
+
+    def test_edit_notification_on(self):
+        result = self.run_command(['user', 'edit-notifications', '--enable', 'Test notification'])
+        self.assert_no_fail(result)
+        self.assert_called_with('SoftLayer_Email_Subscription', 'enable', identifier=111)
+
+    def test_edit_notification_on_bad(self):
+        result = self.run_command(['user', 'edit-notifications', '--enable', 'Test not exist'])
+        self.assertEqual(result.exit_code, 1)
+
+    def test_edit_notifications_off(self):
+        result = self.run_command(['user', 'edit-notifications', '--disable', 'Test notification'])
+        self.assert_no_fail(result)
+        self.assert_called_with('SoftLayer_Email_Subscription', 'disable', identifier=111)
+
+    @mock.patch('SoftLayer.CLI.user.edit_notifications.click')
+    def test_edit_notification_off_failure(self, click):
+        notification = self.set_mock('SoftLayer_Email_Subscription', 'disable')
+        notification.return_value = False
+        result = self.run_command(['user', 'edit-notifications', '--disable', 'Test notification'])
+        click.secho.assert_called_with('Failed to update notifications: Test notification', fg='red')
+        self.assert_no_fail(result)
+        self.assert_called_with('SoftLayer_Email_Subscription', 'disable', identifier=111)
diff --git a/tests/managers/user_tests.py b/tests/managers/user_tests.py
index b0ab015f..61f5b4d0 100644
--- a/tests/managers/user_tests.py
+++ b/tests/managers/user_tests.py
@@ -4,7 +4,9 @@
 
 """
 import datetime
+
 import mock
+
 import SoftLayer
 from SoftLayer import exceptions
 from SoftLayer import testing
@@ -246,3 +248,49 @@ def test_vpn_subnet_remove(self):
         self.manager.vpn_subnet_remove(user_id, [subnet_id])
         self.assert_called_with('SoftLayer_Network_Service_Vpn_Overrides', 'deleteObjects', args=expected_args)
         self.assert_called_with('SoftLayer_User_Customer', 'updateVpnUser', identifier=user_id)
+
+    def test_get_all_notifications(self):
+        self.manager.get_all_notifications()
+        self.assert_called_with('SoftLayer_Email_Subscription', 'getAllObjects')
+
+    def test_enable_notifications(self):
+        self.manager.enable_notifications(['Test notification'])
+        self.assert_called_with('SoftLayer_Email_Subscription', 'enable', identifier=111)
+
+    def test_disable_notifications(self):
+        self.manager.disable_notifications(['Test notification'])
+        self.assert_called_with('SoftLayer_Email_Subscription', 'disable', identifier=111)
+
+    def test_enable_notifications_fail(self):
+        notification = self.set_mock('SoftLayer_Email_Subscription', 'enable')
+        notification.return_value = False
+        result = self.manager.enable_notifications(['Test notification'])
+        self.assert_called_with('SoftLayer_Email_Subscription', 'enable', identifier=111)
+        self.assertFalse(result)
+
+    def test_disable_notifications_fail(self):
+        notification = self.set_mock('SoftLayer_Email_Subscription', 'disable')
+        notification.return_value = False
+        result = self.manager.disable_notifications(['Test notification'])
+        self.assert_called_with('SoftLayer_Email_Subscription', 'disable', identifier=111)
+        self.assertFalse(result)
+
+    def test_gather_notifications(self):
+        expected_result = [
+            {'description': 'Testing description.',
+             'enabled': True,
+             'id': 111,
+             'name': 'Test notification'
+             }
+        ]
+        result = self.manager.gather_notifications(['Test notification'])
+        self.assert_called_with('SoftLayer_Email_Subscription',
+                                'getAllObjects',
+                                mask='mask[enabled]')
+        self.assertEqual(result, expected_result)
+
+    def test_gather_notifications_fail(self):
+        ex = self.assertRaises(SoftLayer.SoftLayerError,
+                               self.manager.gather_notifications,
+                               ['Test not exit'])
+        self.assertEqual("Test not exit is not a valid notification name", str(ex))