Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,50 @@ Events

List of Recognized Events can be found `here <https://github.com/castle/castle-python/tree/master/castle/events.py>`_ or in the `docs <https://docs.castle.io/api_reference/#list-of-recognized-events>`_.

Device management
-----------------

This SDK allows issuing requests to `Castle's Device Management
Endpoints <https://docs.castle.io/device_management_tool/>`__. Use these
endpoints for admin-level management of end-user devices (i.e., for an
internal dashboard).

Fetching device data, approving a device, reporting a device requires a
valid ``device_token``.

.. code:: python

from castle.api.get_device import APIGetDevice

# Get device data
APIGetDevice.call(device_token)

.. code:: python

from castle.api.approve_device import APIApproveDevice

# Approve a device
APIApproveDevice.call(device_token)

.. code:: python

from castle.api.report_device import APIReportDevice

# Report a device
APIReportDevice.call(device_token)


Fetching available devices that belong to a given user requires a valid
``user_id``.

.. code:: python

from castle.api.get_devices_for_user import APIGetDevicesForUser

# Get user's devices data
APIGetDevicesForUser.call(user_id)


Impersonation mode
------------------

Expand Down
2 changes: 1 addition & 1 deletion castle/api/approve_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

class APIApproveDevice(object):
@staticmethod
def retrieve(device_token):
def call(device_token):
return APIRequest().call(CommandsApproveDevice.build(device_token))
2 changes: 1 addition & 1 deletion castle/api/get_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

class APIGetDevice(object):
@staticmethod
def retrieve(device_token):
def call(device_token):
return APIRequest().call(CommandsGetDevice.build(device_token))
8 changes: 0 additions & 8 deletions castle/api/get_devices.py

This file was deleted.

8 changes: 8 additions & 0 deletions castle/api/get_devices_for_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from castle.api_request import APIRequest
from castle.commands.get_devices_for_user import CommandsGetDevicesForUser


class APIGetDevicesForUser(object):
@staticmethod
def call(user_id):
return APIRequest().call(CommandsGetDevicesForUser.build(user_id))
2 changes: 1 addition & 1 deletion castle/api/report_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

class APIReportDevice(object):
@staticmethod
def retrieve(device_token):
def call(device_token):
return APIRequest().call(CommandsReportDevice.build(device_token))
2 changes: 1 addition & 1 deletion castle/api/review.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

class APIReview(object):
@staticmethod
def retrieve(review_id):
def call(review_id):
return APIRequest().call(CommandsReview.build(review_id))
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from castle.validators.present import ValidatorsPresent


class CommandsGetDevices(object):
class CommandsGetDevicesForUser(object):

@staticmethod
def build(user_id):
Expand Down
4 changes: 2 additions & 2 deletions castle/test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
TEST_MODULES = [
'castle.test.api.approve_device_test',
'castle.test.api.get_device_test',
'castle.test.api.get_devices_test',
'castle.test.api.get_devices_for_user_test',
'castle.test.api.report_device_test',
'castle.test.api.review_test',
'castle.test.api_request_test',
Expand All @@ -17,7 +17,7 @@
'castle.test.commands.approve_device_test',
'castle.test.commands.authenticate_test',
'castle.test.commands.get_device_test',
'castle.test.commands.get_devices_test',
'castle.test.commands.get_devices_for_user_test',
'castle.test.commands.identify_test',
'castle.test.commands.impersonate_test',
'castle.test.commands.report_device_test',
Expand Down
4 changes: 2 additions & 2 deletions castle/test/api/approve_device_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def tearDown(self):
configuration.api_secret = None

@responses.activate
def test_retrieve(self):
def test_call(self):
# pylint: disable=line-too-long
response_text = "{\"token\":\"token\",\"created_at\":\"2020-08-13T11:26:47.401Z\",\"last_seen_at\":\"2020-10-18T18:37:22.855Z\",\"user_id\":\"4\",\"approved_at\":\"2020-11-18T12:48:41.112Z\",\"escalated_at\":null,\"mitigated_at\":null,\"context\":{\"ip\":\"127.0.0.1\",\"location\":{\"country_code\":\"PL\",\"country\":\"Poland\"},\"user_agent\":{\"raw\":\"Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/86.0.4240.75 Safari\/537.36\",\"browser\":\"Chrome\",\"version\":\"86.0.4240\",\"os\":\"Mac OS X 10.15.6\",\"mobile\":false,\"platform\":\"Mac OS X\",\"device\":\"Mac\",\"family\":\"Chrome\"},\"properties\":{},\"type\":\"desktop\"},\"is_current_device\":false}"
responses.add(
Expand All @@ -24,4 +24,4 @@ def test_retrieve(self):
status=200
)
device_token = '1234'
self.assertEqual(APIApproveDevice.retrieve(device_token), json.loads(response_text))
self.assertEqual(APIApproveDevice.call(device_token), json.loads(response_text))
4 changes: 2 additions & 2 deletions castle/test/api/get_device_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def tearDown(self):
configuration.api_secret = None

@responses.activate
def test_retrieve(self):
def test_call(self):
# pylint: disable=line-too-long
response_text = "{\"token\":\"token\",\"created_at\":\"2020-08-13T11:26:47.401Z\",\"last_seen_at\":\"2020-10-18T18:37:22.855Z\",\"user_id\":\"4\",\"approved_at\":null,\"escalated_at\":null,\"mitigated_at\":null,\"context\":{\"ip\":\"127.0.0.1\",\"location\":{\"country_code\":\"PL\",\"country\":\"Poland\"},\"user_agent\":{\"raw\":\"Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/86.0.4240.75 Safari\/537.36\",\"browser\":\"Chrome\",\"version\":\"86.0.4240\",\"os\":\"Mac OS X 10.15.6\",\"mobile\":false,\"platform\":\"Mac OS X\",\"device\":\"Mac\",\"family\":\"Chrome\"},\"properties\":{},\"type\":\"desktop\"},\"is_current_device\":false}"
responses.add(
Expand All @@ -24,4 +24,4 @@ def test_retrieve(self):
status=200
)
device_token = '1234'
self.assertEqual(APIGetDevice.retrieve(device_token), json.loads(response_text))
self.assertEqual(APIGetDevice.call(device_token), json.loads(response_text))
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
import responses

from castle.test import unittest
from castle.api.get_devices import APIGetDevices
from castle.api.get_devices_for_user import APIGetDevicesForUser
from castle.configuration import configuration


class APIGetDevicesTestCase(unittest.TestCase):
class APIGetDevicesForUserTestCase(unittest.TestCase):
def setUp(self):
configuration.api_secret = 'test'

def tearDown(self):
configuration.api_secret = None

@responses.activate
def test_retrieve(self):
def test_call(self):
# pylint: disable=line-too-long
response_text = "{\"total_count\":2,\"data\":[{\"token\":\"token\",\"created_at\":\"2020-08-01T18:55:45.352Z\",\"last_seen_at\":\"2020-10-18T21:11:57.476Z\",\"user_id\":\"4\",\"approved_at\":\"2020-08-13T09:55:19.286Z\",\"escalated_at\":null,\"mitigated_at\":null,\"context\":{\"ip\":\"127.0.0.1\",\"location\":{\"country_code\":\"PL\",\"country\":\"Poland\"},\"user_agent\":{\"raw\":\"Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/86.0.4240.75 Safari\/537.36\",\"browser\":\"Chrome\",\"version\":\"86.0.4240\",\"os\":\"Mac OS X 10.15.6\",\"mobile\":false,\"platform\":\"Mac OS X\",\"device\":\"Mac\",\"family\":\"Chrome\"},\"properties\":{},\"type\":\"desktop\"},\"is_current_device\":false},{\"token\":\"token2\",\"created_at\":\"2020-08-13T11:26:47.401Z\",\"last_seen_at\":\"2020-10-18T18:37:22.855Z\",\"user_id\":\"4\",\"approved_at\":null,\"escalated_at\":null,\"mitigated_at\":null,\"context\":{\"ip\":\"127.0.0.1\",\"location\":{\"country_code\":\"PL\",\"country\":\"Poland\"},\"user_agent\":{\"raw\":\"Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/86.0.4240.75 Safari\/537.36\",\"browser\":\"Chrome\",\"version\":\"86.0.4240\",\"os\":\"Mac OS X 10.15.6\",\"mobile\":false,\"platform\":\"Mac OS X\",\"device\":\"Mac\",\"family\":\"Chrome\"},\"properties\":{},\"type\":\"desktop\"},\"is_current_device\":false}]}"
responses.add(
Expand All @@ -24,4 +24,4 @@ def test_retrieve(self):
status=200
)
user_id = '1234'
self.assertEqual(APIGetDevices.retrieve(user_id), json.loads(response_text))
self.assertEqual(APIGetDevicesForUser.call(user_id), json.loads(response_text))
4 changes: 2 additions & 2 deletions castle/test/api/report_device_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def tearDown(self):
configuration.api_secret = None

@responses.activate
def test_retrieve(self):
def test_call(self):
# pylint: disable=line-too-long
response_text = "{\"token\":\"token\",\"created_at\":\"2020-08-13T11:26:47.401Z\",\"last_seen_at\":\"2020-10-18T18:37:22.855Z\",\"user_id\":\"4\",\"approved_at\":\"2020-11-18T12:48:41.112Z\",\"escalated_at\":null,\"mitigated_at\":null,\"context\":{\"ip\":\"127.0.0.1\",\"location\":{\"country_code\":\"PL\",\"country\":\"Poland\"},\"user_agent\":{\"raw\":\"Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/86.0.4240.75 Safari\/537.36\",\"browser\":\"Chrome\",\"version\":\"86.0.4240\",\"os\":\"Mac OS X 10.15.6\",\"mobile\":false,\"platform\":\"Mac OS X\",\"device\":\"Mac\",\"family\":\"Chrome\"},\"properties\":{},\"type\":\"desktop\"},\"is_current_device\":false}"
responses.add(
Expand All @@ -24,4 +24,4 @@ def test_retrieve(self):
status=200
)
device_token = '1234'
self.assertEqual(APIReportDevice.retrieve(device_token), json.loads(response_text))
self.assertEqual(APIReportDevice.call(device_token), json.loads(response_text))
4 changes: 2 additions & 2 deletions castle/test/api/review_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def tearDown(self):
configuration.api_secret = None

@responses.activate
def test_retrieve(self):
def test_call(self):
# pylint: disable=line-too-long
response_text = "{\"id\":\"56b32fa0-880b-0135-74d6-00e650213316\",\"reviewed\":false,\"created_at\":\"2017-09-15T11:59:57.211Z\",\"user_id\":\"1\",\"context\":{\"ip\":\"8.8.8.8\",\"location\":{\"country_code\":\"US\",\"country\":\"United States\",\"region\":null,\"region_code\":null,\"city\":null,\"lat\":37.751,\"lon\":-97.822},\"user_agent\":{\"raw\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36\",\"browser\":\"Chrome\",\"version\":\"60.0.3112\",\"os\":\"Mac OS X 10.12.6\",\"mobile\":false,\"platform\":\"Mac OS X\",\"device\":\"Unknown\",\"family\":\"Chrome\"}}}"
responses.add(
Expand All @@ -24,4 +24,4 @@ def test_retrieve(self):
status=200
)
review_id = '1234'
self.assertEqual(APIReview.retrieve(review_id), json.loads(response_text))
self.assertEqual(APIReview.call(review_id), json.loads(response_text))
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
from castle.test import unittest
from castle.command import Command
from castle.commands.get_devices import CommandsGetDevices
from castle.commands.get_devices_for_user import CommandsGetDevicesForUser
from castle.errors import InvalidParametersError


def user_id():
return '1234'


class CommandsGetDevicesTestCase(unittest.TestCase):
class CommandsGetDevicesForUserTestCase(unittest.TestCase):
def test_build_no_user_id(self):
with self.assertRaises(InvalidParametersError):
CommandsGetDevices.build('')
CommandsGetDevicesForUser.build('')

def test_build(self):
command = CommandsGetDevices.build(user_id())
command = CommandsGetDevicesForUser.build(user_id())
self.assertIsInstance(command, Command)
self.assertEqual(command.method, 'get')
self.assertEqual(command.path, 'users/1234/devices')
Expand Down