Repository: auth0/auth0-python
Pull request #261 (2021-03-30 14:55:11)

Add support for Organization MGMT API endpoints [SDK-2439]
### Changes
Adds endpoints to manage Organizations through the MGMT APIs.

#### Organizations
- POST Organization
- PATCH Organization
- GET Organizations
- GET Organization
- GET Organization (by name)
- DELETE Organization

#### Connections
- POST Organization Connection
- PATCH Organization Connection
- GET Organization Connections
- GET Organization Connection
- DELETE Organization Connection

#### Members
- POST Organization Members
- GET Organization Members
- DELETE Organization Members

#### Member Roles
- POST Organization Member Roles
- GET Organization Member Roles
- DELETE Organization Member Roles

#### Invitations
- POST Organization Invitations
- GET Organization Invitations
- GET Organization Invitation
- DELETE Organization Invitations

#### Users
- GET User Organizations

### References
See `SDK-2439`

### Testing

Unit tests were provided. These endpoints have not been manually tested yet.



Patch:
diff --git a/README.rst b/README.rst
index c39650a..108ea01 100644
--- a/README.rst
+++ b/README.rst
@@ -347,6 +347,7 @@ Available Management Endpoints
 - Jobs() ( ``Auth0().jobs`` )
 - Logs() ( ``Auth0().logs`` )
 - LogStreams() ( ``Auth0().log_streams`` )
+- Organizations() ( ``Auth0().organizations`` )
 - ResourceServers() (``Auth0().resource_servers`` )
 - Roles() ( ``Auth0().roles`` )
 - Rules() ( ``Auth0().rules`` )
diff --git a/auth0/v3/management/auth0.py b/auth0/v3/management/auth0.py
index 262760d..5f4ab47 100644
--- a/auth0/v3/management/auth0.py
+++ b/auth0/v3/management/auth0.py
@@ -12,6 +12,7 @@ from .hooks import Hooks
 from .jobs import Jobs
 from .log_streams import LogStreams
 from .logs import Logs
+from .organizations import Organizations
 from .resource_servers import ResourceServers
 from .roles import Roles
 from .rules import Rules
@@ -48,6 +49,7 @@ class Auth0(object):
         self.jobs = Jobs(domain, token)
         self.logs = Logs(domain, token)
         self.log_streams = LogStreams(domain, token)
+        self.organizations = Organizations(domain, token)
         self.resource_servers = ResourceServers(domain, token)
         self.roles = Roles(domain, token)
         self.rules = Rules(domain, token)
diff --git a/auth0/v3/management/organizations.py b/auth0/v3/management/organizations.py
new file mode 100644
index 0000000..bbb72e9
--- /dev/null
+++ b/auth0/v3/management/organizations.py
@@ -0,0 +1,349 @@
+from .rest import RestClient
+
+
+class Organizations(object):
+    """Auth0 organizations endpoints
+
+    Args:
+        domain (str): Your Auth0 domain, e.g: 'username.auth0.com'
+
+        token (str): Management API v2 Token
+
+        telemetry (bool, optional): Enable or disable Telemetry
+            (defaults to True)
+
+        timeout (float or tuple, optional): Change the requests
+            connect and read timeout. Pass a tuple to specify
+            both values separately or a float to set both to it.
+            (defaults to 5.0 for both)
+    """
+
+    def __init__(self, domain, token, telemetry=True, timeout=5.0, protocol="https"):
+        self.domain = domain
+        self.protocol = protocol
+        self.client = RestClient(jwt=token, telemetry=telemetry, timeout=timeout)
+
+    def _url(self, *args):
+        url = '{}://{}/api/v2/organizations'.format(self.protocol, self.domain)
+        for p in args:
+            if p is not None:
+                url = '{}/{}'.format(url, p)
+        return url
+
+    # Organizations
+    def all_organizations(self, page=None, per_page=None):
+        """Retrieves a list of all the organizations.
+
+        Args:
+           page (int): The result's page number (zero based). When not set,
+              the default value is up to the server.
+
+           per_page (int, optional): The amount of entries per page. When not set,
+              the default value is up to the server.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/get_organizations
+        """
+        params = {}
+        params['page'] = page
+        params['per_page'] = per_page
+
+        return self.client.get(self._url(), params=params)
+
+    def get_organization_by_name(self, name=None):
+        """Retrieves an organization given its name.
+
+        Args:
+           name (str): The name of the organization to retrieve.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/get_name_by_name
+        """
+        params = {}
+        params['name'] = name
+
+        return self.client.get(self._url(), params=params)
+    
+    def get_organization(self, id):
+        """Retrieves an organization by its ID.
+
+        Args:
+           id (str): Id of organization to retrieve.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/get_organizations_by_id
+        """
+        params = {}
+
+        return self.client.get(self._url(id), params=params)
+
+    def create_organization(self, body):
+        """Create a new organization.
+
+        Args:
+           body (dict): Attributes for the new organization.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/post_organizations
+        """
+
+        return self.client.post(self._url(), data=body)
+    
+    def update_organization(self, id, body):
+        """Modifies an organization.
+
+        Args:
+           id (str): the ID of the organization.
+
+           body (dict): Attributes to modify.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/patch_organizations_by_id
+        """
+
+        return self.client.patch(self._url(id), data=body)
+
+    def delete_organization(self, id):
+        """Deletes an organization and all its related assets.
+
+        Args:
+           id (str): Id of organization to delete.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/delete_organizations_by_id
+        """
+
+        return self.client.delete(self._url(id))
+
+
+    # Organization Connections
+    def all_organization_connections(self, id, page=None, per_page=None):
+        """Retrieves a list of all the organization connections.
+
+        Args:
+           id (str): the ID of the organization.
+
+           page (int): The result's page number (zero based). When not set,
+              the default value is up to the server.
+
+           per_page (int, optional): The amount of entries per page. When not set,
+              the default value is up to the server.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/get_enabled_connections
+        """
+        params = {}
+        params['page'] = page
+        params['per_page'] = per_page
+
+        return self.client.get(self._url(id, 'enabled_connections'), params=params)
+
+    def get_organization_connection(self, id, connection_id):
+        """Retrieves an organization connection by its ID.
+
+        Args:
+           id (str): the ID of the organization.
+
+           connection_id (str): the ID of the connection.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/get_enabled_connections_by_connectionId
+        """
+        params = {}
+
+        return self.client.get(self._url(id, 'enabled_connections', connection_id), params=params)
+
+    def create_organization_connection(self, id, body):
+        """Adds a connection to an organization.
+
+        Args:
+           id (str): the ID of the organization.
+
+           body (dict): Attributes for the connection to add.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/post_enabled_connections
+        """
+
+        return self.client.post(self._url(id, 'enabled_connections'), data=body)
+    
+    def update_organization_connection(self, id, connection_id, body):
+        """Modifies an organization.
+
+        Args:
+           id (str): the ID of the organization.
+
+           connection_id (str): the ID of the connection to update.
+
+           body (dict): Attributes to modify.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/patch_enabled_connections_by_connectionId
+        """
+
+        return self.client.patch(self._url(id, 'enabled_connections', connection_id), data=body)
+
+    def delete_organization_connection(self, id, connection_id):
+        """Deletes a connection from the given organization.
+
+        Args:
+           id (str): Id of organization.
+
+           connection_id (str): the ID of the connection to delete.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/delete_enabled_connections_by_connectionId
+        """
+
+        return self.client.delete(self._url(id, 'enabled_connections', connection_id))
+
+    # Organization Members
+    def all_organization_members(self, id, page=None, per_page=None):
+        """Retrieves a list of all the organization members.
+
+        Args:
+           id (str): the ID of the organization.
+
+           page (int): The result's page number (zero based). When not set,
+              the default value is up to the server.
+
+           per_page (int, optional): The amount of entries per page. When not set,
+              the default value is up to the server.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/get_members
+        """
+        params = {}
+        params['page'] = page
+        params['per_page'] = per_page
+
+        return self.client.get(self._url(id, 'members'), params=params)
+
+    def create_organization_members(self, id, body):
+        """Adds members to an organization.
+
+        Args:
+           id (str): the ID of the organization.
+
+           body (dict): Attributes from the members to add.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/post_members
+        """
+
+        return self.client.post(self._url(id, 'members'), data=body)
+
+    def delete_organization_members(self, id, body):
+        """Deletes members from the given organization.
+
+        Args:
+           id (str): Id of organization.
+
+           body (dict): Attributes from the members to delete
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/delete_members
+        """
+
+        return self.client.delete(self._url(id, 'members'), data=body)
+
+    # Organization Member Roles
+    def all_organization_member_roles(self, id, user_id, page=None, per_page=None):
+        """Retrieves a list of all the roles from the given organization member.
+
+        Args:
+           id (str): the ID of the organization.
+           
+           user_id (str): the ID of the user member of the organization.
+
+           page (int): The result's page number (zero based). When not set,
+              the default value is up to the server.
+
+           per_page (int, optional): The amount of entries per page. When not set,
+              the default value is up to the server.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/get_organization_member_roles
+        """
+        params = {}
+        params['page'] = page
+        params['per_page'] = per_page
+
+        return self.client.get(self._url(id, 'members', user_id, 'roles'), params=params)
+
+    def create_organization_member_roles(self, id, user_id, body):
+        """Adds roles to a member of an organization.
+
+        Args:
+           id (str): the ID of the organization.
+
+           user_id (str): the ID of the user member of the organization.
+
+           body (dict): Attributes from the members to add.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/post_organization_member_roles
+        """
+
+        return self.client.post(self._url(id, 'members', user_id, 'roles'), data=body)
+
+    def delete_organization_member_roles(self, id, user_id, body):
+        """Deletes roles from a member of an organization.
+
+        Args:
+           id (str): Id of organization.
+
+           user_id (str): the ID of the user member of the organization.
+
+           body (dict): Attributes from the members to delete
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/delete_organization_member_roles
+        """
+
+        return self.client.delete(self._url(id, 'members', user_id, 'roles'), data=body)
+
+
+    # Organization Invitations
+    def all_organization_invitations(self, id, page=None, per_page=None):
+        """Retrieves a list of all the organization invitations.
+
+        Args:
+           id (str): the ID of the organization.
+
+           page (int): The result's page number (zero based). When not set,
+              the default value is up to the server.
+
+           per_page (int, optional): The amount of entries per page. When not set,
+              the default value is up to the server.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/get_invitations
+        """
+        params = {}
+        params['page'] = page
+        params['per_page'] = per_page
+
+        return self.client.get(self._url(id, 'invitations'), params=params)
+
+    def get_organization_invitation(self, id, invitaton_id):
+        """Retrieves an organization invitation by its ID.
+
+        Args:
+           id (str): the ID of the organization.
+
+           invitaton_id (str): the ID of the invitation.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/get_invitations_by_invitation_id
+        """
+        params = {}
+
+        return self.client.get(self._url(id, 'invitations', invitaton_id), params=params)
+
+    def create_organization_invitation(self, id, body):
+        """Create an invitation to an organization.
+
+        Args:
+           id (str): the ID of the organization.
+
+           body (dict): Attributes for the invitation to create.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/post_invitations
+        """
+
+        return self.client.post(self._url(id, 'invitations'), data=body)
+   
+    def delete_organization_invitation(self, id, invitation_id):
+        """Deletes an invitation from the given organization.
+
+        Args:
+           id (str): Id of organization.
+
+           invitation_id (str): the ID of the invitation to delete.
+
+        See: https://auth0.com/docs/api/management/v2#!/Organizations/delete_invitations_by_invitation_id
+        """
+
+        return self.client.delete(self._url(id, 'invitations', invitation_id))
diff --git a/auth0/v3/management/users.py b/auth0/v3/management/users.py
index 09ec966..b4c20e7 100644
--- a/auth0/v3/management/users.py
+++ b/auth0/v3/management/users.py
@@ -145,6 +145,32 @@ class Users(object):
         """
         return self.client.patch(self._url(id), data=body)
 
+    def list_organizations(self, id, page=0, per_page=25, include_totals=True):
+        """List the organizations that the user is member of.
+
+        Args:
+            id (str): The user's id.
+
+            page (int, optional): The result's page number (zero based). By default,
+               retrieves the first page of results.
+
+            per_page (int, optional): The amount of entries per page. By default,
+               retrieves 25 results per page.
+
+            include_totals (bool, optional): True if the query summary is
+               to be included in the result, False otherwise. Defaults to True.
+
+        See https://auth0.com/docs/api/management/v2#!/Users/get_organizations
+        """
+        params = {
+            'per_page': per_page,
+            'page': page,
+            'include_totals': str(include_totals).lower()
+        }
+
+        url = self._url('{}/organizations'.format(id))
+        return self.client.get(url, params=params)
+
     def list_roles(self, id, page=0, per_page=25, include_totals=True):
         """List the roles associated with a user.
 


Test patch:
diff --git a/auth0/v3/test/management/test_auth0.py b/auth0/v3/test/management/test_auth0.py
index da4d550..1031fd6 100644
--- a/auth0/v3/test/management/test_auth0.py
+++ b/auth0/v3/test/management/test_auth0.py
@@ -15,6 +15,7 @@ from ...management.hooks import Hooks
 from ...management.jobs import Jobs
 from ...management.log_streams import LogStreams
 from ...management.logs import Logs
+from ...management.organizations import Organizations
 from ...management.resource_servers import ResourceServers
 from ...management.roles import Roles
 from ...management.rules import Rules
@@ -76,6 +77,9 @@ class TestAuth0(unittest.TestCase):
     def test_log_streams(self):
         self.assertIsInstance(self.a0.log_streams, LogStreams)
 
+    def test_organizations(self):
+        self.assertIsInstance(self.a0.organizations, Organizations)
+
     def test_resource_servers(self):
         self.assertIsInstance(self.a0.resource_servers, ResourceServers)
 
diff --git a/auth0/v3/test/management/test_organizations.py b/auth0/v3/test/management/test_organizations.py
new file mode 100644
index 0000000..babb7fe
--- /dev/null
+++ b/auth0/v3/test/management/test_organizations.py
@@ -0,0 +1,326 @@
+import unittest
+import mock
+from ...management.organizations import Organizations
+
+
+class TestOrganizations(unittest.TestCase):
+
+    def test_init_with_optionals(self):
+        t = Organizations(domain='domain', token='jwttoken', telemetry=False, timeout=(10, 2))
+        self.assertEqual(t.client.timeout, (10, 2))
+        telemetry_header = t.client.base_headers.get('Auth0-Client', None)
+        self.assertEqual(telemetry_header, None)
+
+    # Organizations
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_all_organizations(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+
+        # Default parameters are requested
+        c.all_organizations()
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations', args[0])
+        self.assertEqual(kwargs['params'], {'page': None,
+                                            'per_page': None})
+
+        # Specific pagination
+        c.all_organizations(page=7, per_page=25)
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations', args[0])
+        self.assertEqual(kwargs['params'], {'page': 7,
+                                            'per_page': 25})
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_get_organization_by_name(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.get_organization_by_name('test-org')
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations', args[0])
+        self.assertEqual(kwargs['params'], {'name': 'test-org'})
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_get_organization(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.get_organization('org123')
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/org123', args[0])
+        self.assertEqual(kwargs['params'], {})
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_create_organization(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.create_organization({'a': 'b', 'c': 'd'})
+
+        mock_instance.post.assert_called_with(
+            'https://domain/api/v2/organizations',
+            data={'a': 'b', 'c': 'd'}
+        )
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_update_organization(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.update_organization('this-id', {'a': 'b', 'c': 'd'})
+
+        args, kwargs = mock_instance.patch.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/this-id', args[0])
+        self.assertEqual(kwargs['data'], {'a': 'b', 'c': 'd'})
+   
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_delete_organization(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.delete_organization('this-id')
+
+        mock_instance.delete.assert_called_with(
+            'https://domain/api/v2/organizations/this-id'
+        )
+    
+    # Organization Connections
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_all_organization_connections(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+
+        # Default parameters are requested
+        c.all_organization_connections('test-org')
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/enabled_connections', args[0])
+        self.assertEqual(kwargs['params'], {'page': None,
+                                            'per_page': None})
+
+        # Specific pagination
+        c.all_organization_connections('test-org', page=7, per_page=25)
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/enabled_connections', args[0])
+        self.assertEqual(kwargs['params'], {'page': 7,
+                                            'per_page': 25})
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_get_organization_connection(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.get_organization_connection('test-org', 'test-con')
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/enabled_connections/test-con', args[0])
+        self.assertEqual(kwargs['params'], {})
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_create_organization_connection(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.create_organization_connection('test-org', {'a': 'b', 'c': 'd'})
+
+        mock_instance.post.assert_called_with(
+            'https://domain/api/v2/organizations/test-org/enabled_connections',
+            data={'a': 'b', 'c': 'd'}
+        )
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_update_organization_connection(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.update_organization_connection('test-org', 'test-con', {'a': 'b', 'c': 'd'})
+
+        args, kwargs = mock_instance.patch.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/enabled_connections/test-con', args[0])
+        self.assertEqual(kwargs['data'], {'a': 'b', 'c': 'd'})
+   
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_delete_organization_connection(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.delete_organization_connection('test-org', 'test-con')
+
+        mock_instance.delete.assert_called_with(
+            'https://domain/api/v2/organizations/test-org/enabled_connections/test-con'
+        )
+
+    # Organization Members
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_all_organization_members(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+
+        # Default parameters are requested
+        c.all_organization_members('test-org')
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/members', args[0])
+        self.assertEqual(kwargs['params'], {'page': None,
+                                            'per_page': None})
+
+        # Specific pagination
+        c.all_organization_members('test-org', page=7, per_page=25)
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/members', args[0])
+        self.assertEqual(kwargs['params'], {'page': 7,
+                                            'per_page': 25})
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_create_organization_members(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.create_organization_members('test-org', {'a': 'b', 'c': 'd'})
+
+        mock_instance.post.assert_called_with(
+            'https://domain/api/v2/organizations/test-org/members',
+            data={'a': 'b', 'c': 'd'}
+        )
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_delete_organization_members(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.delete_organization_members('test-org', {'a': 'b', 'c': 'd'})
+
+        mock_instance.delete.assert_called_with(
+            'https://domain/api/v2/organizations/test-org/members',
+            data={'a': 'b', 'c': 'd'}
+        )
+
+    # Organization Member Roles
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_all_organization_member_roles(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+
+        # Default parameters are requested
+        c.all_organization_member_roles('test-org', 'test-user')
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/members/test-user/roles', args[0])
+        self.assertEqual(kwargs['params'], {'page': None,
+                                            'per_page': None})
+
+        # Specific pagination
+        c.all_organization_member_roles('test-org', 'test-user', page=7, per_page=25)
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/members/test-user/roles', args[0])
+        self.assertEqual(kwargs['params'], {'page': 7,
+                                            'per_page': 25})
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_create_organization_member_roles(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.create_organization_member_roles('test-org', 'test-user', {'a': 'b', 'c': 'd'})
+
+        mock_instance.post.assert_called_with(
+            'https://domain/api/v2/organizations/test-org/members/test-user/roles',
+            data={'a': 'b', 'c': 'd'}
+        )
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_delete_organization_member_roles(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.delete_organization_member_roles('test-org', 'test-user', {'a': 'b', 'c': 'd'})
+
+        mock_instance.delete.assert_called_with(
+            'https://domain/api/v2/organizations/test-org/members/test-user/roles',
+            data={'a': 'b', 'c': 'd'}
+        )
+
+    # Organization Invitations
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_all_organization_invitations(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+
+        # Default parameters are requested
+        c.all_organization_invitations('test-org')
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/invitations', args[0])
+        self.assertEqual(kwargs['params'], {'page': None,
+                                            'per_page': None})
+
+        # Specific pagination
+        c.all_organization_invitations('test-org', page=7, per_page=25)
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/invitations', args[0])
+        self.assertEqual(kwargs['params'], {'page': 7,
+                                            'per_page': 25})
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_get_organization_invitation(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.get_organization_invitation('test-org', 'test-inv')
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/organizations/test-org/invitations/test-inv', args[0])
+        self.assertEqual(kwargs['params'], {})
+
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_create_organization_invitation(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.create_organization_invitation('test-org', {'a': 'b', 'c': 'd'})
+
+        mock_instance.post.assert_called_with(
+            'https://domain/api/v2/organizations/test-org/invitations',
+            data={'a': 'b', 'c': 'd'}
+        )
+   
+    @mock.patch('auth0.v3.management.organizations.RestClient')
+    def test_delete_organization_invitation(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        c = Organizations(domain='domain', token='jwttoken')
+        c.delete_organization_invitation('test-org', 'test-inv')
+
+        mock_instance.delete.assert_called_with(
+            'https://domain/api/v2/organizations/test-org/invitations/test-inv'
+        )
diff --git a/auth0/v3/test/management/test_users.py b/auth0/v3/test/management/test_users.py
index 359876e..8e03f7e 100644
--- a/auth0/v3/test/management/test_users.py
+++ b/auth0/v3/test/management/test_users.py
@@ -119,6 +119,32 @@ class TestUsers(unittest.TestCase):
         self.assertEqual('https://domain/api/v2/users/an-id', args[0])
         self.assertEqual(kwargs['data'], {'a': 'b', 'c': 'd'})
 
+    @mock.patch('auth0.v3.management.users.RestClient')
+    def test_list_organizations(self, mock_rc):
+        mock_instance = mock_rc.return_value
+
+        u = Users(domain='domain', token='jwttoken')
+        u.list_organizations('an-id')
+
+        args, kwargs = mock_instance.get.call_args
+        self.assertEqual('https://domain/api/v2/users/an-id/organizations', args[0])
+        self.assertEqual(kwargs['params'], {
+            'per_page': 25,
+            'page': 0,
+            'include_totals': 'true'
+        })
+
+        u.list_organizations(id='an-id', page=1, per_page=50, include_totals=False)
+
+        args, kwargs = mock_instance.get.call_args
+
+        self.assertEqual('https://domain/api/v2/users/an-id/organizations', args[0])
+        self.assertEqual(kwargs['params'], {
+            'per_page': 50,
+            'page': 1,
+            'include_totals': 'false'
+        })
+
     @mock.patch('auth0.v3.management.users.RestClient')
     def test_list_roles(self, mock_rc):
         mock_instance = mock_rc.return_value