Skip to content

Commit f011fd8

Browse files
author
Maria Korlotian
authored
CAS-6600/api changes (#101)
1 parent b2f8847 commit f011fd8

30 files changed

Lines changed: 265 additions & 449 deletions

README.rst

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,10 @@ Here is a simple example of track event.
118118
.. code:: python
119119
120120
from castle.client import Client
121-
from castle import events
122121
123122
castle = Client.from_request(request)
124123
castle.track({
125-
'event': events.LOGIN_SUCCEEDED,
124+
'event': '$login',
126125
'user_id': 'user_id'
127126
})
128127
@@ -148,11 +147,10 @@ background worker you can generate data for a worker:
148147
.. code:: python
149148
150149
from castle.payload.prepare import PayloadPrepare
151-
from castle import events
152150
153151
payload = PayloadPrepare.call(
154152
{
155-
'event': events.LOGIN_SUCCEEDED,
153+
'event': '$login',
156154
'user_id': user.id,
157155
'properties': { 'key': 'value' },
158156
'user_traits': { 'key': 'value' }
@@ -172,7 +170,7 @@ and use it later in a way
172170
Events
173171
--------------
174172

175-
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>`_.
173+
List of Recognized Events can be found in the `docs <https://docs.castle.io/api_reference/#list-of-recognized-events>`_.
176174

177175
Device management
178176
-----------------
@@ -234,7 +232,7 @@ error <https://github.com/castle/castle-python/blob/master/castle/errors.py>`__.
234232
Webhooks
235233
--------
236234

237-
Castle uses webhooks to notify about ``$incident.confirmed`` or `$review.opened` events.
235+
Castle uses webhooks to notify about ``$incident.confirmed`` or ``$review.opened`` events.
238236
Each webhook has ``X-Castle-Signature`` header that allows verifying webhook's source.
239237

240238
.. code:: python

castle/api/review.py

Lines changed: 0 additions & 9 deletions
This file was deleted.

castle/client.py

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from castle.api_request import APIRequest
22
from castle.commands.authenticate import CommandsAuthenticate
3-
from castle.commands.identify import CommandsIdentify
43
from castle.commands.start_impersonation import CommandsStartImpersonation
54
from castle.commands.end_impersonation import CommandsEndImpersonation
65
from castle.commands.track import CommandsTrack
76
from castle.configuration import configuration
87
from castle.context.prepare import ContextPrepare
8+
from castle.options.merge import OptionsMerge
9+
from castle.options.get_default import OptionsGetDefault
910
from castle.errors import InternalServerError, RequestError, ImpersonationFailed
1011
from castle.failover.prepare_response import FailoverPrepareResponse
1112
from castle.failover.strategy import FailoverStrategy
@@ -18,8 +19,11 @@ def from_request(cls, request, options=None):
1819
if options is None:
1920
options = {}
2021

21-
options.setdefault('context', ContextPrepare.call(request, options))
22-
return cls(options)
22+
default_options = OptionsGetDefault(request, options.get('cookies')).call()
23+
options_with_default_opts = OptionsMerge.call(options, default_options)
24+
25+
options_with_default_opts.setdefault('context', ContextPrepare.call(options))
26+
return cls(options_with_default_opts)
2327

2428
@staticmethod
2529
def failover_response_or_raise(options, exception):
@@ -32,6 +36,8 @@ def failover_response_or_raise(options, exception):
3236
def __init__(self, options=None):
3337
if options is None:
3438
options = {}
39+
40+
self.default_options = options
3541
self.do_not_track = options.get('do_not_track', False)
3642
self.timestamp = options.get('timestamp')
3743
self.context = options.get('context')
@@ -42,47 +48,51 @@ def _add_timestamp_if_necessary(self, options):
4248
options.setdefault('timestamp', self.timestamp)
4349

4450
def authenticate(self, options):
51+
options_with_default_opts = OptionsMerge.call(options, self.default_options)
52+
4553
if self.tracked():
46-
self._add_timestamp_if_necessary(options)
47-
command = CommandsAuthenticate(self.context).call(options)
54+
self._add_timestamp_if_necessary(options_with_default_opts)
55+
command = CommandsAuthenticate(self.context).call(options_with_default_opts)
4856
try:
4957
response = self.api.call(command)
5058
response.update(failover=False, failover_reason=None)
5159
return response
5260
except (RequestError, InternalServerError) as exception:
53-
return Client.failover_response_or_raise(options, exception)
61+
return Client.failover_response_or_raise(options_with_default_opts, exception)
5462
else:
5563
return FailoverPrepareResponse(
56-
options.get('user_id'),
64+
options_with_default_opts.get('user_id'),
5765
'allow',
5866
'Castle set to do not track.'
5967
).call()
6068

61-
def identify(self, options):
62-
if not self.tracked():
63-
return None
64-
self._add_timestamp_if_necessary(options)
65-
return self.api.call(CommandsIdentify(self.context).call(options))
66-
6769
def start_impersonation(self, options):
68-
self._add_timestamp_if_necessary(options)
69-
response = self.api.call(CommandsStartImpersonation(self.context).call(options))
70+
options_with_default_opts = OptionsMerge.call(options, self.default_options)
71+
72+
self._add_timestamp_if_necessary(options_with_default_opts)
73+
response = self.api.call(CommandsStartImpersonation(
74+
self.context).call(options_with_default_opts))
7075
if not response.get('success'):
7176
raise ImpersonationFailed
7277
return response
7378

7479
def end_impersonation(self, options):
75-
self._add_timestamp_if_necessary(options)
76-
response = self.api.call(CommandsEndImpersonation(self.context).call(options))
80+
options_with_default_opts = OptionsMerge.call(options, self.default_options)
81+
82+
self._add_timestamp_if_necessary(options_with_default_opts)
83+
response = self.api.call(CommandsEndImpersonation(
84+
self.context).call(options_with_default_opts))
7785
if not response.get('success'):
7886
raise ImpersonationFailed
7987
return response
8088

8189
def track(self, options):
90+
options_with_default_opts = OptionsMerge.call(options, self.default_options)
91+
8292
if not self.tracked():
8393
return None
84-
self._add_timestamp_if_necessary(options)
85-
return self.api.call(CommandsTrack(self.context).call(options))
94+
self._add_timestamp_if_necessary(options_with_default_opts)
95+
return self.api.call(CommandsTrack(self.context).call(options_with_default_opts))
8696

8797
def disable_tracking(self):
8898
self.do_not_track = True

castle/commands/end_impersonation.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ def __init__(self, context):
1010
self.context = context
1111

1212
def call(self, options):
13-
ValidatorsPresent.call(options, 'user_id')
13+
ValidatorsPresent.call(options, 'user_id', 'headers')
1414

1515
context = ContextMerge.call(self.context, options.get('context'))
1616
context = ContextSanitize.call(context)
17-
ValidatorsPresent.call(context, 'user_agent', 'ip')
1817

1918
if context:
2019
options.update({'context': context})

castle/commands/identify.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

castle/commands/review.py

Lines changed: 0 additions & 15 deletions
This file was deleted.

castle/commands/start_impersonation.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ def __init__(self, context):
1010
self.context = context
1111

1212
def call(self, options):
13-
ValidatorsPresent.call(options, 'user_id')
13+
ValidatorsPresent.call(options, 'user_id', 'headers')
1414

1515
context = ContextMerge.call(self.context, options.get('context'))
1616
context = ContextSanitize.call(context)
17-
ValidatorsPresent.call(context, 'user_agent', 'ip')
1817

1918
if context:
2019
options.update({'context': context})

castle/context/get_default.py

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,18 @@
11
from castle.version import VERSION
2-
from castle.headers.filter import HeadersFilter
3-
from castle.client_id.extract import ClientIdExtract
4-
from castle.headers.extract import HeadersExtract
5-
from castle.ips.extract import IPsExtract
62

73
__version__ = VERSION
84

95

106
class ContextGetDefault(object):
11-
def __init__(self, request, cookies):
12-
self.cookies = self._fetch_cookies(request, cookies)
13-
self.pre_headers = HeadersFilter(request).call()
147

15-
def call(self):
8+
@staticmethod
9+
def call():
1610
context = dict({
17-
'client_id': self._client_id(),
1811
'active': True,
19-
'headers': self._headers(),
20-
'ip': self._ip(),
2112
'library': {
2213
'name': 'castle-python',
2314
'version': __version__
2415
}
2516
})
26-
context.update(self._optional_defaults())
27-
28-
return context
29-
30-
def _ip(self):
31-
return IPsExtract(self.pre_headers).call()
3217

33-
def _client_id(self):
34-
return ClientIdExtract(self.pre_headers, self.cookies).call()
35-
36-
def _headers(self):
37-
return HeadersExtract(self.pre_headers).call()
38-
39-
def _optional_defaults(self):
40-
context = dict()
41-
if 'Accept-Language' in self.pre_headers:
42-
context['locale'] = self.pre_headers.get('Accept-Language')
43-
if 'User-Agent' in self.pre_headers:
44-
context['user_agent'] = self.pre_headers.get('User-Agent')
4518
return context
46-
47-
@staticmethod
48-
def _fetch_cookies(request, cookies):
49-
if cookies:
50-
return cookies
51-
if hasattr(request, 'COOKIES') and request.COOKIES:
52-
return request.COOKIES
53-
return None

castle/context/prepare.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55
class ContextPrepare(object):
66

77
@staticmethod
8-
def call(request, options=None):
8+
def call(options=None):
99
if options is None:
1010
options = {}
11-
default_context = ContextGetDefault(
12-
request, options.get('cookies')).call()
11+
default_context = ContextGetDefault.call()
1312
return ContextMerge.call(default_context, options.get('context', {}))

castle/events.py

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)