Repository: box/box-python-sdk
Pull request #327 (2018-08-21 01:31:17)

Storage Policies v2

boxcla: Hi @carycheng, thanks for the pull request. Before we can merge it, we need you to sign our Contributor License Agreement. You can do so electronically here: http://opensource.box.com/cla

Once you have signed, just add a comment to this pull request saying, "CLA signed". Thanks!
mattwiller: Left some comments and feedback.  Also, remember to add the new object types to object/__init__.py
coveralls: ## Pull Request Test Coverage Report for [Build 1208](https://coveralls.io/builds/19709992)

* **34** of **36**   **(94.44%)**  changed or added relevant lines in **4** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage decreased (**-0.01%**) to **95.242%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [boxsdk/client/client.py](https://coveralls.io/builds/19709992/source?filename=boxsdk%2Fclient%2Fclient.py#L755) | 4 | 6 | 66.67%
<!-- | **Total:** | **34** | **36** | **94.44%** | -->


|  Totals | [![Coverage Status](https://coveralls.io/builds/19709992/badge)](https://coveralls.io/builds/19709992) |
| :-- | --: |
| Change from base [Build 1203](https://coveralls.io/builds/19707399): |  -0.01% |
| Covered Lines: | 2182 |
| Relevant Lines: | 2291 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/boxsdk/client/client.py b/boxsdk/client/client.py
index 2253598..f0c43a2 100644
--- a/boxsdk/client/client.py
+++ b/boxsdk/client/client.py
@@ -692,6 +692,66 @@ def create_group(
             response_object=response,
         )
 
+    def storage_policy(self, policy_id):
+        """
+        Initialize a :class:`StoragePolicy` object, whose box id is policy_id.
+
+        :param policy_id:
+            The box ID of the :class:`StoragePolicy` object.
+        :type policy_id:
+            `unicode`
+        :return:
+            A :class:`StoragePolicy` object with the given entry ID.
+        :rtype:
+            :class:`StoragePolicy`
+        """
+        return self.translator.get('storage_policy')(session=self._session, object_id=policy_id)
+
+    def storage_policy_assignment(self, assignment_id):
+        """
+        Initialize a :class:`StoragePolicyAssignment` object, whose box id is assignment_id.
+
+        :param assignment_id:
+            The box ID of the :class:`StoragePolicyAssignment` object.
+        :type assignment_id:
+            `unicode`
+        :return:
+            A :class:`StoragePolicyAssignment` object with the given entry ID.
+        :rtype:
+            :class:`StoragePolicyAssignment`
+        """
+        return self.translator.get('storage_policy_assignment')(session=self._session, object_id=assignment_id)
+
+    def get_storage_policies(self, limit=None, marker=None, fields=None):
+        """
+        Get the entries in the storage policy using marker-based paging.
+
+        :param limit:
+            The maximum number of items to return.
+        :type limit:
+            `int` or None
+        :param marker:
+            The paging marker to start returning items from when using marker-based paging.
+        :type marker:
+            `unicode` or None
+        :param fields:
+            List of fields to request.
+        :type fields:
+            `Iterable` of `unicode`
+        :returns:
+            Returns the storage policies available for the current enterprise.
+        :rtype:
+            :class:`BoxObjectCollection`
+        """
+        return MarkerBasedObjectCollection(
+            session=self._session,
+            url=self.get_url('storage_policies'),
+            limit=limit,
+            marker=marker,
+            fields=fields,
+            return_full_pages=False,
+        )
+
     def terms_of_service(self, tos_id):
         """
         Initialize a :class:`TermsOfService` object, whose box id is tos_id.
diff --git a/boxsdk/object/__init__.py b/boxsdk/object/__init__.py
index ee03b2a..fe99b77 100644
--- a/boxsdk/object/__init__.py
+++ b/boxsdk/object/__init__.py
@@ -28,6 +28,8 @@
     'retention_policy',
     'retention_policy_assignment',
     'search',
+    'storage_policy',
+    'storage_policy_assignment',
     'terms_of_service',
     'terms_of_service_user_status',
     'trash',
diff --git a/boxsdk/object/storage_policy.py b/boxsdk/object/storage_policy.py
new file mode 100644
index 0000000..ad62b0c
--- /dev/null
+++ b/boxsdk/object/storage_policy.py
@@ -0,0 +1,77 @@
+# coding:utf-8
+from __future__ import unicode_literals, absolute_import
+
+import json
+
+from .base_object import BaseObject
+
+
+class StoragePolicy(BaseObject):
+    """Represents the storage policy"""
+
+    _item_type = 'storage_policy'
+
+    def get_url(self, *args):
+        """
+        Get url for storage policies.
+        """
+        return self._session.get_url('storage_policies', self._object_id, *args)
+
+    def assign(self, user):
+        """
+        Checks to see if a user is already assigned a storage policy or if the storage policy assigned
+        to user belongs to the enterprise. If neither, then update the user storage policy to the new one.
+
+        :param user:
+            The class:`User` to assign the storage policy to
+        :type user:
+            :class:`User`
+        :returns:
+            Information about the :class:`StoragePolicyAssignment` object.
+        :rtype:
+            :class:`StoragePolicyAssignment`
+        """
+        assignment = user.get_storage_policy_assignment()
+        if assignment.id == self.object_id:
+            return assignment
+
+        if assignment.assigned_to['type'] == 'enterprise':
+            return self.create_assignment(user)
+
+        update_object = {
+            'storage_policy': {
+                'type': self.object_type,
+                'id': self.object_id,
+            },
+        }
+        return assignment.update_info(update_object)
+
+    def create_assignment(self, user):
+        """
+        Assign a storage policy to a :class:`User`.
+
+        :param user:
+            The :class:'User` to assign the storage policy to.
+        :type:
+            :class:`User`
+        :returns:
+            Information about the :class:`StoragePolicyAssignment` object
+        :rtype:
+            :class:`StoragePolicyAssignment`
+        """
+        url = self._session.get_url('storage_policy_assignments')
+        body = {
+            'storage_policy': {
+                'type': 'storage_policy',
+                'id': self.object_id,
+            },
+            'assigned_to': {
+                'type': user.object_type,
+                'id': user.object_id,
+            }
+        }
+        response = self._session.post(url, data=json.dumps(body)).json()
+        return self.translator.translate(
+            session=self._session,
+            response_object=response,
+        )
diff --git a/boxsdk/object/storage_policy_assignment.py b/boxsdk/object/storage_policy_assignment.py
new file mode 100644
index 0000000..01b14fa
--- /dev/null
+++ b/boxsdk/object/storage_policy_assignment.py
@@ -0,0 +1,9 @@
+# coding:utf-8
+from __future__ import unicode_literals, absolute_import
+from .base_object import BaseObject
+
+
+class StoragePolicyAssignment(BaseObject):
+    """Represents the storage policy assignment"""
+
+    _item_type = 'storage_policy_assignment'
diff --git a/boxsdk/object/user.py b/boxsdk/object/user.py
index 09663ab..e1d576e 100644
--- a/boxsdk/object/user.py
+++ b/boxsdk/object/user.py
@@ -12,6 +12,27 @@ class User(BaseObject):
 
     _item_type = 'user'
 
+    def get_storage_policy_assignment(self):
+        """
+        Get the storage policy assignment assigned to the user.
+
+        :returns:
+            The :class:`StoragePolicyAssignment` object information
+        :rtype:
+            :class:`StoragePolicyAssignment`
+        """
+        url = self._session.get_url('storage_policy_assignments')
+        additional_params = {
+            'resolved_for_type': self.object_type,
+            'resolved_for_id': self.object_id,
+        }
+        box_response = self._session.get(url, params=additional_params)
+        response = box_response.json()['entries'][0]
+        return self.translator.translate(
+            session=self._session,
+            response_object=response,
+        )
+
     @api_call
     def get_group_memberships(self, limit=None, offset=None, fields=None):
         """
diff --git a/docs/storage_policy.md b/docs/storage_policy.md
new file mode 100644
index 0000000..788fc31
--- /dev/null
+++ b/docs/storage_policy.md
@@ -0,0 +1,91 @@
+Storage Policy 
+==============
+
+Allows the enterprise admin to manage the Storage Policies for users in their
+enterprise. Used for an enterprise to decide storage location for users based on
+where they work/reside. 
+
+
+Get Storage Policy
+------------------
+
+Calling `storage_policy.get(fields=None)` will return the storage policy object.
+
+```python
+storage_policy_id = '1234'
+storage_policy = client.storage_policy(storage_policy_id).get()
+```
+
+List Available Storage Policies
+-------------------------------
+
+Calling `client.get_storage_policies()` will return an iterable that will page through all of the storage policies. It is possible to specify maxiumum number of items per response and fields to retrieve by caling `client.get_storage_policies(limit=None, fields=None)`.
+
+```python
+storage_policies = client.get_storage_policies(limit=100)
+for storage_policy in storage_policies:
+    # Do something
+```
+
+Create Storage Policy Assignment
+--------------------------------
+
+To create new storage policy assignment call `storage_policy.create_assignment(user)`.
+
+```python
+storage_policy_id = '5678'
+user = client.user('1234')
+storage_policy_assignment = client.storage_policy(storage_policy_id).create_assignment(user)
+```
+
+Note: This method only works if the user does not already have an assignment. If the current state of the user is not known, use the `storage_policy.assign(user)` method instead.
+
+Assign a Storage Policy to a User
+---------------------------------
+
+To assign a storage policy to a user, call the `storage_policy.assign(user)` method with the user to assign the storage policy to.
+
+```python
+user = client.user('1234')
+storage_policy_assignment = client.storage_policy('12345').assign(user)
+```
+
+Update Existing Assignment
+--------------------------
+
+Updating a storage policy assignment is done by calling `storage_policy.update_info(update_item)`.
+
+```python
+updated_storage_policy = {'storage_policy': {'type': 'storage_policy', 'id': '1234'}}
+updated_assignment = client.storage_policy_assignment('ZW50ZXJwcmldfgeV82MDMwMDQ=').update_info(updated_storage_policy)
+```
+
+Get Assignment
+--------------
+
+Calling `storage_policy_assignment.get(fields=None)` will return a storage policy assignment object containing information about the assignment.
+
+```python
+assignment_id = '1234'
+storage_policy_assignment = client.storage_policy_assignment(assignment_id).get()
+```
+
+Get Assignment for User
+-------------------------
+
+Calling `user.get_storage_policy_assignment()` will return the storage policy assigned to the specified user.
+
+```python
+user_id = '1111'
+assignment_info = client.user(user_id).get_storage_policy_assignment()
+```
+
+Delete Assignment
+-----------------
+
+Calling `storage_policy_assignment.delete()` will remove the storage policy assignment from the user.
+
+```python
+assignment_id = '1234'
+client.storage_policy_assignment(assignment_id).delete()
+```


Test patch:
diff --git a/test/unit/client/test_client.py b/test/unit/client/test_client.py
index 217512e..be9faf6 100644
--- a/test/unit/client/test_client.py
+++ b/test/unit/client/test_client.py
@@ -26,6 +26,8 @@
 from boxsdk.object.folder import Folder
 from boxsdk.object.file import File
 from boxsdk.object.group import Group
+from boxsdk.object.storage_policy import StoragePolicy
+from boxsdk.object.storage_policy_assignment import StoragePolicyAssignment
 from boxsdk.object.terms_of_service import TermsOfService
 from boxsdk.object.user import User
 from boxsdk.object.trash import Trash
@@ -367,7 +369,9 @@ def device_pins_response(device_pin_id_1, device_pin_id_2):
     (Group, 'group'),
     (GroupMembership, 'group_membership'),
     (Enterprise, 'enterprise'),
-    (Webhook, 'webhook')
+    (Webhook, 'webhook'),
+    (StoragePolicy, 'storage_policy'),
+    (StoragePolicyAssignment, 'storage_policy_assignment'),
 ])
 def test_factory_returns_the_correct_object(mock_client, test_class, factory_method_name):
     """ Tests the various id-only factory methods in the Client class """
@@ -632,6 +636,26 @@ def test_create_enterprise_user_returns_the_correct_user_object(mock_client, moc
     assert new_user.name == test_user_name
 
 
+def test_get_storage_policies(mock_client, mock_box_session):
+    expected_url = mock_box_session.get_url('storage_policies')
+    mock_policy = {
+        'type': 'storage_policy',
+        'id': '12345',
+        'name': 'Test Storage Policy'
+    }
+    mock_box_session.get.return_value.json.return_value = {
+        'limit': 100,
+        'entries': [mock_policy]
+    }
+    policies = mock_client.get_storage_policies()
+    policy = policies.next()
+    mock_box_session.get.assert_called_once_with(expected_url, params={})
+    assert isinstance(policy, StoragePolicy)
+    assert policy.type == 'storage_policy'
+    assert policy.id == '12345'
+    assert policy.name == 'Test Storage Policy'
+
+
 def test_create_terms_of_service(mock_client, mock_box_session):
     # pylint:disable=redefined-outer-name
     expected_url = "{0}/terms_of_services".format(API.BASE_API_URL)
diff --git a/test/unit/object/conftest.py b/test/unit/object/conftest.py
index 6e9bf52..6625efa 100644
--- a/test/unit/object/conftest.py
+++ b/test/unit/object/conftest.py
@@ -22,6 +22,8 @@
 from boxsdk.object.retention_policy import RetentionPolicy
 from boxsdk.object.retention_policy_assignment import RetentionPolicyAssignment
 from boxsdk.object.search import Search
+from boxsdk.object.storage_policy import StoragePolicy
+from boxsdk.object.storage_policy_assignment import StoragePolicyAssignment
 from boxsdk.object.terms_of_service import TermsOfService
 from boxsdk.object.terms_of_service_user_status import TermsOfServiceUserStatus
 from boxsdk.object.collaboration_whitelist import CollaborationWhitelist
@@ -161,6 +163,16 @@ def test_search(mock_box_session):
     return Search(mock_box_session)
 
 
+@pytest.fixture()
+def test_storage_policy(mock_box_session, mock_object_id):
+    return StoragePolicy(mock_box_session, mock_object_id)
+
+
+@pytest.fixture()
+def test_storage_policy_assignment(mock_box_session, mock_object_id):
+    return StoragePolicyAssignment(mock_box_session, mock_object_id)
+
+
 @pytest.fixture()
 def test_terms_of_service(mock_box_session, mock_object_id):
     return TermsOfService(mock_box_session, mock_object_id)
diff --git a/test/unit/object/test_storage_policy.py b/test/unit/object/test_storage_policy.py
new file mode 100644
index 0000000..6d28846
--- /dev/null
+++ b/test/unit/object/test_storage_policy.py
@@ -0,0 +1,175 @@
+# coding: utf-8
+from __future__ import unicode_literals
+
+import json
+from boxsdk.config import API
+from boxsdk.object.storage_policy import StoragePolicy
+from boxsdk.object.storage_policy_assignment import StoragePolicyAssignment
+
+
+def test_get(test_storage_policy, mock_box_session):
+    expected_url = '{0}/storage_policies/{1}'.format(API.BASE_API_URL, test_storage_policy.object_id)
+    mock_box_session.get.return_value.json.return_value = {
+        'type': test_storage_policy.object_type,
+        'id': test_storage_policy.object_id,
+    }
+    storage_policy = test_storage_policy.get()
+    mock_box_session.get.assert_called_once_with(expected_url, headers=None, params=None)
+    assert isinstance(storage_policy, StoragePolicy)
+
+
+def test_assign_with_same_assignment(test_storage_policy, test_storage_policy_assignment, mock_user, mock_box_session):
+    expected_url = '{0}/storage_policy_assignments'.format(API.BASE_API_URL)
+    additional_params = {
+        'resolved_for_type': mock_user.object_type,
+        'resolved_for_id': mock_user.object_id,
+    }
+    mock_box_session.get.return_value.json.return_value = {
+        'next_marker': None,
+        'limit': 1,
+        'entries': [
+            {
+                'type': test_storage_policy_assignment.object_type,
+                'id': test_storage_policy_assignment.object_id,
+                'storage_policy': {
+                    'type': test_storage_policy.object_type,
+                    'id': test_storage_policy.object_id,
+                },
+            },
+        ],
+    }
+    assignment = test_storage_policy.assign(mock_user)
+    mock_box_session.get.assert_called_once_with(expected_url, params=additional_params)
+    assert isinstance(assignment, StoragePolicyAssignment)
+    assert assignment.type == test_storage_policy_assignment.object_type
+    assert assignment.id == test_storage_policy_assignment.object_id
+    assert assignment.storage_policy['type'] == test_storage_policy.object_type
+    assert assignment.storage_policy['id'] == test_storage_policy.object_id
+
+
+def test_assign_with_assigned_enterprise(test_storage_policy, test_storage_policy_assignment, mock_user, mock_box_session):
+    expected_url = '{0}/storage_policy_assignments'.format(API.BASE_API_URL)
+    additional_params = {
+        'resolved_for_type': mock_user.object_type,
+        'resolved_for_id': mock_user.object_id,
+    }
+    expected_data = {
+        'storage_policy': {
+            'type': test_storage_policy.object_type,
+            'id': test_storage_policy.object_id,
+        },
+        'assigned_to': {
+            'type': mock_user.object_type,
+            'id': mock_user.object_id,
+        },
+    }
+    mock_box_session.get.return_value.json.return_value = {
+        'next_marker': None,
+        'limit': 1,
+        'entries': [
+            {
+                'type': test_storage_policy_assignment.object_type,
+                'id': '11111',
+                'storage_policy': {
+                    'type': test_storage_policy.object_type,
+                    'id': '22222',
+                },
+                'assigned_to': {
+                    'type': 'enterprise',
+                    'id': '12345',
+                },
+            },
+        ],
+    }
+    mock_box_session.post.return_value.json.return_value = {
+        'type': test_storage_policy_assignment.object_type,
+        'id': test_storage_policy_assignment.object_id,
+        'storage_policy': {
+            'type': test_storage_policy.object_type,
+            'id': test_storage_policy.object_id
+        }
+    }
+    assignment = test_storage_policy.assign(mock_user)
+    mock_box_session.get.assert_called_once_with(expected_url, params=additional_params)
+    mock_box_session.post.assert_called_once_with(expected_url, data=json.dumps(expected_data))
+    assert isinstance(assignment, StoragePolicyAssignment)
+    assert assignment.type == test_storage_policy_assignment.object_type
+    assert assignment.id == test_storage_policy_assignment.object_id
+    assert assignment.storage_policy['type'] == test_storage_policy.object_type
+    assert assignment.storage_policy['id'] == test_storage_policy.object_id
+
+
+def test_assign_with_update(test_storage_policy, test_storage_policy_assignment, mock_user, mock_box_session):
+    expected_url = '{0}/storage_policy_assignments'.format(API.BASE_API_URL)
+    expected_put_url = '{0}/storage_policy_assignments/{1}'.format(API.BASE_API_URL, '11111')
+    additional_params = {
+        'resolved_for_type': mock_user.object_type,
+        'resolved_for_id': mock_user.object_id,
+    }
+    expected_data = {
+        'storage_policy': {
+            'type': test_storage_policy.object_type,
+            'id': '42',
+        },
+    }
+    mock_box_session.get.return_value.json.return_value = {
+        'next_marker': None,
+        'limit': 1,
+        'entries': [
+            {
+                'type': test_storage_policy_assignment.object_type,
+                'id': '11111',
+                'storage_policy': {
+                    'type': test_storage_policy.object_type,
+                    'id': '22222',
+                },
+                'assigned_to': {
+                    'type': 'user',
+                    'id': '12345',
+                },
+            },
+        ],
+    }
+    mock_box_session.put.return_value.json.return_value = {
+        'type': test_storage_policy_assignment.object_type,
+        'id': test_storage_policy_assignment.object_id,
+        'storage_policy': {
+            'type': test_storage_policy.object_type,
+            'id': '42'
+        }
+    }
+    assignment = test_storage_policy.assign(mock_user)
+    mock_box_session.get.assert_called_once_with(expected_url, params=additional_params)
+    mock_box_session.put.assert_called_once_with(expected_put_url, data=json.dumps(expected_data), headers=None, params=None)
+    assert isinstance(assignment, StoragePolicyAssignment)
+    assert assignment.type == test_storage_policy_assignment.object_type
+    assert assignment.id == test_storage_policy_assignment.object_id
+    assert assignment.storage_policy['type'] == test_storage_policy.object_type
+    assert assignment.storage_policy['id'] == '42'
+
+
+def test_create_assignment(test_storage_policy, mock_user, mock_box_session):
+    expected_url = '{0}/storage_policy_assignments'.format(API.BASE_API_URL)
+    expected_data = {
+        'storage_policy': {
+            'type': 'storage_policy',
+            'id': '42',
+        },
+        'assigned_to': {
+            'type': 'user',
+            'id': 'fake-user-100',
+        },
+    }
+    mock_assignment = {
+        'type': 'storage_policy_assignment',
+        'id': '1234',
+        'storage_policy': {
+            'type': test_storage_policy.object_type,
+            'id': test_storage_policy.object_id,
+        },
+    }
+    mock_box_session.post.return_value.json.return_value = mock_assignment
+    assignment = test_storage_policy.create_assignment(mock_user)
+    mock_box_session.post.assert_called_once_with(expected_url, data=json.dumps(expected_data))
+    assert assignment.id == mock_assignment['id']
+    assert assignment.storage_policy['id'] == mock_assignment['storage_policy']['id']
diff --git a/test/unit/object/test_storage_policy_assignment.py b/test/unit/object/test_storage_policy_assignment.py
new file mode 100644
index 0000000..decca98
--- /dev/null
+++ b/test/unit/object/test_storage_policy_assignment.py
@@ -0,0 +1,60 @@
+# coding: utf-8
+from __future__ import unicode_literals, absolute_import
+
+import json
+import pytest
+
+from mock import Mock
+from boxsdk.config import API
+from boxsdk.object.storage_policy_assignment import StoragePolicyAssignment
+from boxsdk.network.default_network import DefaultNetworkResponse
+
+
+@pytest.fixture(scope='module')
+def delete_assignment_response():
+    # pylint:disable=redefined-outer-name
+    mock_network_response = Mock(DefaultNetworkResponse)
+    mock_network_response.ok = True
+    return mock_network_response
+
+
+def test_get(test_storage_policy_assignment, mock_box_session):
+    expected_url = '{0}/storage_policy_assignments/{1}'.format(API.BASE_API_URL, test_storage_policy_assignment.object_id)
+    mock_box_session.get.return_value.json.return_value = {
+        'type': 'storage_policy_assignment',
+        'id': test_storage_policy_assignment.object_id,
+    }
+    storage_policy_assignment = test_storage_policy_assignment.get()
+    mock_box_session.get.assert_called_once_with(expected_url, headers=None, params=None)
+    assert isinstance(storage_policy_assignment, StoragePolicyAssignment)
+
+
+def test_update(test_storage_policy_assignment, mock_box_session):
+    new_policy_id = '1234'
+    expected_url = '{0}/storage_policy_assignments/{1}'.format(API.BASE_API_URL, test_storage_policy_assignment.object_id)
+    mock_box_session.get.return_value.json.return_value = {
+        'type': 'storage_policy_assignment',
+        'id': new_policy_id,
+    }
+    storage_policy_assignment = test_storage_policy_assignment.update_info({
+        'storage_policy': {
+            'type': 'storage_policy',
+            'id': new_policy_id,
+        }
+    })
+    data = {
+        'storage_policy': {
+            'type': 'storage_policy',
+            'id': new_policy_id,
+        }
+    }
+    mock_box_session.put.assert_called_once_with(expected_url, data=json.dumps(data), headers=None, params=None)
+    assert isinstance(storage_policy_assignment, StoragePolicyAssignment)
+
+
+def test_delete(test_storage_policy_assignment, delete_assignment_response, mock_box_session):
+    mock_box_session.delete.return_value = delete_assignment_response
+    response = test_storage_policy_assignment.delete()
+    expected_url = test_storage_policy_assignment.get_url()
+    mock_box_session.delete.assert_called_once_with(expected_url, params={}, expect_json_response=False, headers=None)
+    assert response is True
diff --git a/test/unit/object/test_user.py b/test/unit/object/test_user.py
index 2ea14a3..796c096 100644
--- a/test/unit/object/test_user.py
+++ b/test/unit/object/test_user.py
@@ -5,6 +5,7 @@
 
 from mock import Mock
 from boxsdk.config import API
+from boxsdk.object.storage_policy_assignment import StoragePolicyAssignment
 from boxsdk.network.default_network import DefaultNetworkResponse
 
 
@@ -13,6 +14,32 @@ def test_user_url(mock_user):
     assert mock_user.get_url() == '{0}/{1}/{2}'.format(API.BASE_API_URL, 'users', mock_user.object_id)
 
 
+def test_get_storage_policy_assignments(test_storage_policy_assignment, mock_user, mock_box_session):
+    expected_url = mock_box_session.get_url('storage_policy_assignments')
+    mock_assignment = {
+        'type': test_storage_policy_assignment.object_type,
+        'id': test_storage_policy_assignment.object_id,
+        'assigned_to': {
+            'type': mock_user.object_type,
+            'id': mock_user.object_id,
+        },
+    }
+    mock_box_session.get.return_value.json.return_value = {
+        'next_marker': None,
+        'limit': 1,
+        'entries': [mock_assignment],
+    }
+    expected_params = {
+        'resolved_for_type': mock_user.object_type,
+        'resolved_for_id': mock_user.object_id,
+    }
+    assignment = mock_user.get_storage_policy_assignment()
+    mock_box_session.get.assert_called_once_with(expected_url, params=expected_params)
+    assert isinstance(assignment, StoragePolicyAssignment)
+    assert assignment.id == mock_assignment['id']
+    assert assignment.type == mock_assignment['type']
+
+
 @pytest.fixture(scope='module')
 def memberships_response():
     # pylint disable=redefined-outer-name