Skip to content

Commit c7721fa

Browse files
committed
Add support for the Admint Audit Events API
Add the API wrapper, data model, tests, and update the docs.
1 parent b572727 commit c7721fa

File tree

8 files changed

+420
-19
lines changed

8 files changed

+420
-19
lines changed

docs/user/api.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ access_tokens
3131
.. autoclass:: webexteamssdk.api.access_tokens.AccessTokensAPI()
3232

3333

34+
.. _admin_audit_events:
35+
36+
admin_audit_events
37+
------------------
38+
39+
.. autoclass:: webexteamssdk.api.admin_audit_events.AdminAuditEventsAPI()
40+
3441

3542
.. _attachment_actions
3643
@@ -153,7 +160,10 @@ Access Token
153160

154161
.. _Admin_Audit_Event:
155162

163+
Admin Audit Event
164+
-----------------
156165

166+
.. autoclass:: AdminAuditEvent()
157167
:inherited-members:
158168

159169

docs/user/api_structure_table.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
| :class:`WebexTeamsAPI` | :ref:`access_tokens` | :meth:`get() <webeteamssdk.api.access_tokens.AccessTokensAPI.get>` |
33
| | | :meth:`refresh() <webeteamssdk.api.access_tokens.AccessTokensAPI.refresh>` |
44
+------------------------+---------------------------+---------------------------------------------------------------------------------+
5+
| | :ref:`admin_audit_events` | :meth:`list() <webexteamssdk.api.admin_audit_events.list>` |
6+
+------------------------+---------------------------+---------------------------------------------------------------------------------+
57
| | :ref:`attachment_actions` | :meth:`create() <webexteamssdk.api.attachment_actions.create>` |
68
| | | :meth:`get() <webexteamssdk.api.attachment_actions.get>` |
79
+------------------------+---------------------------+---------------------------------------------------------------------------------+

tests/api/test_admin_audit_events.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# -*- coding: utf-8 -*-
2+
"""WebexTeamsAPI Admin Audit Events API fixtures and tests.
3+
4+
Copyright (c) 2016-2019 Cisco and/or its affiliates.
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
"""
24+
25+
import itertools
26+
27+
import pytest
28+
29+
import webexteamssdk
30+
31+
32+
from_datetime_string = str(
33+
webexteamssdk.WebexTeamsDateTime(2018, 1, 1, 0, 0, 0, 0),
34+
)
35+
36+
to_datetime_string = str(
37+
webexteamssdk.WebexTeamsDateTime.utcnow(),
38+
)
39+
40+
41+
# Helper Functions
42+
43+
def is_valid_admin_audit_event(obj):
44+
return isinstance(obj, webexteamssdk.AdminAuditEvent) \
45+
and obj.id is not None
46+
47+
48+
def are_valid_admin_audit_events(iterable):
49+
return all([is_valid_admin_audit_event(obj) for obj in iterable])
50+
51+
52+
# Fixtures
53+
54+
@pytest.fixture(scope="session")
55+
def admin_audit_events(api, me):
56+
three_events = list(api.admin_audit_events.list(
57+
orgId=me.orgId,
58+
_from=from_datetime_string,
59+
to=to_datetime_string,
60+
)[:3])
61+
assert len(three_events) == 3
62+
return three_events
63+
64+
65+
# Tests
66+
67+
def test_list_admin_audit_events(api, admin_audit_events):
68+
assert are_valid_admin_audit_events(admin_audit_events)
69+
70+
71+
def test_list_admin_audit_events_by_actor_id(api, admin_audit_events):
72+
actor_id = admin_audit_events[0].actorId
73+
actor_events = list(api.events.list(actorId=actor_id)[:3])
74+
assert are_valid_admin_audit_events(actor_events)
75+
assert all([event.actorId == actor_id for event in actor_events])
76+
77+
78+
@pytest.mark.xfail # TODO: Returned link headers are malformed on the endpoint
79+
def test_list_events_with_paging(api, me, admin_audit_events):
80+
page_size = 1
81+
pages = 3
82+
num_events = pages * page_size
83+
assert len(admin_audit_events) >= num_events
84+
events_gen = api.admin_audit_events.list(
85+
orgId=me.orgId,
86+
_from=from_datetime_string,
87+
to=to_datetime_string,
88+
max=page_size,
89+
)
90+
events_list = list(itertools.islice(events_gen, num_events))
91+
assert len(events_list) == num_events
92+
assert are_valid_admin_audit_events(events_list)

webexteamssdk/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242
)
4343
from .models.dictionary import dict_data_factory
4444
from .models.immutable import (
45-
AccessToken, AttachmentAction, Event, immutable_data_factory, License,
46-
Membership, Message, Organization, Person, Role, Room, Team,
47-
TeamMembership, Webhook, WebhookEvent,
45+
AccessToken, AdminAuditEvent, AttachmentAction, Event,
46+
immutable_data_factory, License, Membership, Message, Organization, Person,
47+
Role, Room, Team, TeamMembership, Webhook, WebhookEvent,
4848
)
4949
from .models.simple import simple_data_factory, SimpleDataModel
5050
from .utils import WebexTeamsDateTime

webexteamssdk/api/__init__.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from webexteamssdk.restsession import RestSession
3535
from webexteamssdk.utils import check_type
3636
from .access_tokens import AccessTokensAPI
37+
from .admin_audit_events import AdminAuditEventsAPI
3738
from .attachment_actions import AttachmentActionsAPI
3839
from .events import EventsAPI
3940
from .guest_issuer import GuestIssuerAPI
@@ -172,23 +173,26 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
172173
)
173174

174175
# API wrappers
175-
self.people = PeopleAPI(self._session, object_factory)
176-
self.rooms = RoomsAPI(self._session, object_factory)
176+
self.admin_audit_events = AdminAuditEventsAPI(
177+
self._session, object_factory,
178+
)
179+
self.attachment_actions = AttachmentActionsAPI(
180+
self._session, object_factory,
181+
)
182+
self.events = EventsAPI(self._session, object_factory)
183+
self.guest_issuer = GuestIssuerAPI(self._session, object_factory)
184+
self.licenses = LicensesAPI(self._session, object_factory)
177185
self.memberships = MembershipsAPI(self._session, object_factory)
178186
self.messages = MessagesAPI(self._session, object_factory)
187+
self.organizations = OrganizationsAPI(self._session, object_factory)
188+
self.people = PeopleAPI(self._session, object_factory)
189+
self.roles = RolesAPI(self._session, object_factory)
190+
self.rooms = RoomsAPI(self._session, object_factory)
179191
self.teams = TeamsAPI(self._session, object_factory)
180192
self.team_memberships = TeamMembershipsAPI(
181-
self._session, object_factory
182-
)
183-
self.attachment_actions = AttachmentActionsAPI(
184-
self._session, object_factory
193+
self._session, object_factory,
185194
)
186195
self.webhooks = WebhooksAPI(self._session, object_factory)
187-
self.organizations = OrganizationsAPI(self._session, object_factory)
188-
self.licenses = LicensesAPI(self._session, object_factory)
189-
self.roles = RolesAPI(self._session, object_factory)
190-
self.events = EventsAPI(self._session, object_factory)
191-
self.guest_issuer = GuestIssuerAPI(self._session, object_factory)
192196

193197
@property
194198
def access_token(self):
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# -*- coding: utf-8 -*-
2+
"""Webex Admin Audit Events API wrapper.
3+
4+
Copyright (c) 2016-2019 Cisco and/or its affiliates.
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
"""
24+
25+
26+
from __future__ import (
27+
absolute_import,
28+
division,
29+
print_function,
30+
unicode_literals,
31+
)
32+
33+
from builtins import *
34+
35+
from past.builtins import basestring
36+
37+
from webexteamssdk.generator_containers import generator_container
38+
from webexteamssdk.restsession import RestSession
39+
from webexteamssdk.utils import check_type, dict_from_items_with_values
40+
41+
42+
API_ENDPOINT = 'adminAudit/events'
43+
OBJECT_TYPE = 'admin_audit_event'
44+
45+
46+
class AdminAuditEventsAPI(object):
47+
"""Admin Audit Events API.
48+
49+
Wraps the Webex Teams Admin Audit Events API and exposes the API as native
50+
Python methods that return native Python objects.
51+
52+
"""
53+
54+
def __init__(self, session, object_factory):
55+
"""Init a new AdminAuditEventsAPI object with the provided RestSession.
56+
57+
Args:
58+
session(RestSession): The RESTful session object to be used for
59+
API calls to the Webex Teams service.
60+
61+
Raises:
62+
TypeError: If the parameter types are incorrect.
63+
64+
"""
65+
check_type(session, RestSession)
66+
67+
super(AdminAuditEventsAPI, self).__init__()
68+
69+
self._session = session
70+
self._object_factory = object_factory
71+
72+
@generator_container
73+
def list(self, orgId, _from, to, actorId=None, max=100, offset=0,
74+
**request_parameters):
75+
"""List Organizations.
76+
77+
This method supports Webex Teams's implementation of RFC5988 Web
78+
Linking to provide pagination support. It returns a generator
79+
container that incrementally yields all audit events returned by the
80+
query. The generator will automatically request additional 'pages' of
81+
responses from Webex as needed until all responses have been returned.
82+
The container makes the generator safe for reuse. A new API call will
83+
be made, using the same parameters that were specified when the
84+
generator was created, every time a new iterator is requested from the
85+
container.
86+
87+
Args:
88+
orgId(basestring): List events in this organization, by ID.
89+
_from(basestring): List events which occurred after a specific
90+
date and time.
91+
to(basestring): List events which occurred before a specific date
92+
and time.
93+
actorId(basestring): List events performed by this person, by ID.
94+
max(int): Limit the maximum number of events in the response. The
95+
maximum value is 200.
96+
offset(int): Offset from the first result that you want to fetch.
97+
**request_parameters: Additional request parameters (provides
98+
support for parameters that may be added in the future).
99+
100+
Returns:
101+
GeneratorContainer: A GeneratorContainer which, when iterated,
102+
yields the organizations returned by the Webex Teams query.
103+
104+
Raises:
105+
TypeError: If the parameter types are incorrect.
106+
ApiError: If the Webex Teams cloud returns an error.
107+
"""
108+
check_type(orgId, basestring)
109+
check_type(_from, basestring)
110+
check_type(to, basestring)
111+
check_type(actorId, basestring, optional=True)
112+
check_type(max, int)
113+
check_type(offset, int)
114+
115+
params = dict_from_items_with_values(
116+
request_parameters,
117+
orgId=orgId,
118+
_from=_from,
119+
to=to,
120+
actorId=actorId,
121+
max=max,
122+
offset=offset,
123+
)
124+
125+
if _from:
126+
params["from"] = params.pop("_from")
127+
128+
# API request - get items
129+
items = self._session.get_items(API_ENDPOINT, params=params)
130+
131+
# Yield AdminAuditEvent objects created from the returned JSON objects
132+
for item in items:
133+
yield self._object_factory(OBJECT_TYPE, item)

webexteamssdk/models/immutable.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,24 @@
3030
"""
3131

3232
from __future__ import (
33-
absolute_import,
34-
division,
35-
print_function,
36-
unicode_literals,
33+
absolute_import, absolute_import, division, division,
34+
print_function, print_function, unicode_literals, unicode_literals,
3735
)
3836

3937
from builtins import *
38+
4039
import json
4140
from collections import defaultdict
4241

4342
from webexteamssdk.utils import json_dict
4443
from .mixins.access_token import AccessTokenBasicPropertiesMixin
44+
from .mixins.admin_audit_event import (
45+
AdminAuditEventBasicPropertiesMixin,
46+
AdminAuditEventDataBasicPropertiesMixin,
47+
)
4548
from .mixins.attachment_action import AttachmentActionBasicPropertiesMixin
4649
from .mixins.event import EventBasicPropertiesMixin
50+
from .mixins.guest_issuer_token import GuestIssuerTokenBasicPropertiesMixin
4751
from .mixins.license import LicenseBasicPropertiesMixin
4852
from .mixins.membership import MembershipBasicPropertiesMixin
4953
from .mixins.message import MessageBasicPropertiesMixin
@@ -55,7 +59,6 @@
5559
from .mixins.team_membership import TeamMembershipBasicPropertiesMixin
5660
from .mixins.webhook import WebhookBasicPropertiesMixin
5761
from .mixins.webhook_event import WebhookEventBasicPropertiesMixin
58-
from .mixins.guest_issuer_token import GuestIssuerTokenBasicPropertiesMixin
5962

6063

6164
class ImmutableData(object):
@@ -178,6 +181,20 @@ class AccessToken(ImmutableData, AccessTokenBasicPropertiesMixin):
178181
"""Webex Teams Access-Token data model."""
179182

180183

184+
class AdminAuditEventData(ImmutableData,
185+
AdminAuditEventDataBasicPropertiesMixin):
186+
"""Webex Teams Admin Audit Event Data object data model."""
187+
188+
189+
class AdminAuditEvent(ImmutableData, AdminAuditEventBasicPropertiesMixin):
190+
"""Webex Teams Admin Audit Event data model."""
191+
192+
@property
193+
def data(self):
194+
"""The event resource data."""
195+
return AdminAuditEventData(self._json_data.get('data'))
196+
197+
181198
class AttachmentAction(ImmutableData, AttachmentActionBasicPropertiesMixin):
182199
"""Webex Attachment Actions data model"""
183200

@@ -251,6 +268,7 @@ class GuestIssuerToken(ImmutableData, GuestIssuerTokenBasicPropertiesMixin):
251268
immutable_data_models = defaultdict(
252269
lambda: ImmutableData,
253270
access_token=AccessToken,
271+
admin_audit_event=AdminAuditEvent,
254272
attachment_action=AttachmentAction,
255273
event=Event,
256274
license=License,

0 commit comments

Comments
 (0)