Skip to content

Commit

Permalink
Merge pull request #60 from koshilife/feature/#59_support_activity_log
Browse files Browse the repository at this point in the history
support Activity Log API
  • Loading branch information
koshilife committed Nov 6, 2022
2 parents b6d1e74 + 66b87e5 commit fcdb320
Show file tree
Hide file tree
Showing 9 changed files with 334 additions and 1 deletion.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# CHANGELOG

## 0.14.0 - 2022-11-06

- supported Activity Log API. (#59, thanks to Calendly gave us a sample JSON file)
- `GET /activity_log_entries`
- changed were followings:
- Client
- (Add method) activity_log_entries
- Organization model
- (Add method) activity_log_entries

## 0.13.0 - 2022-08-03

- supported List Event Type Available Times API. (#57)
Expand Down
34 changes: 34 additions & 0 deletions lib/calendly/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,40 @@ def delete_invitee_data(emails)
true
end

#
# Returns a list of activity log entries.
#
# @param [String] org_uri Return activity log entries from the organization associated with this URI.
# @param [Hash] options the optional request parameters. Optional.
# @option options [Array<String>] :action The action(s) associated with the entries.
# @option options [Array<String>] :actor Return entries from the user(s) associated with the provided URIs.
# @option options [Integer] :count The number of rows to return.
# @option options [String] :max_occurred_at include entries that occurred prior to this time.
# @option options [String] :min_occurred_at Include entries that occurred after this time.
# @option options [Array<String>] :namespace The categories of the entries.
# @option options [String] :page_token The token to pass to get the next portion of the collection.
# @option options [String] :search_term Filters entries based on the search term.
# @option options [Array<String>] :sort Order results by the specified field and direction. List of {field}:{direction} values.
# @return [Array<Array<Calendly::ActivityLogEntry>, Hash, Hash>]
# - [Array<Calendly::ActivityLogEntry>] log_entries
# - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
# - [Hash] raw_response
# @raise [Calendly::Error] if the org_uri arg is empty.
# @raise [Calendly::ApiError] if the api returns error code.
# @since 0.14.0
def activity_log_entries(org_uri, options: nil)
check_not_empty org_uri, 'org_uri'

opts_keys = %i[action actor count max_occurred_at min_occurred_at namespace page_token search_term sort]
params = {organization: org_uri}
params = merge_options options, opts_keys, params
body = request :get, 'activity_log_entries', params: params

items = body[:collection] || []
log_entries = items.map { |item| ActivityLogEntry.new item, self }
[log_entries, next_page_params(body), body]
end

#
# Returns information about a user's organization membership
#
Expand Down
50 changes: 50 additions & 0 deletions lib/calendly/models/activity_log_entry.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

module Calendly
# Calendly's activity log entry model.
class ActivityLogEntry
include ModelUtils
UUID_RE = %r{\A#{Client::API_HOST}/activity_log_entries/(#{UUID_FORMAT})\z}.freeze
TIME_FIELDS = %i[occurred_at].freeze

def self.association
{
organization: Organization
}
end

# @return [String]
# unique id of the ActivityLogEntry object.
attr_accessor :uuid

# @return [String]
# Canonical reference (unique identifier) for the activity log entry.
attr_accessor :uri

# @return [Time]
# The date and time of the entry.
attr_accessor :occurred_at

# @return [Hash]
# The Calendly actor that took the action creating the activity log entry.
attr_accessor :actor

# @return [Hash]
attr_accessor :details

# @return [String]
attr_accessor :fully_qualified_name

# @return [String]
# The category associated with the entry.
attr_accessor :namespace

# @return [String]
# The action associated with the entry.
attr_accessor :action

# @return [Organization]
# The organization associated with the entry.
attr_accessor :organization
end
end
24 changes: 24 additions & 0 deletions lib/calendly/models/organization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -193,5 +193,29 @@ def routing_forms!(options: nil)
@cached_routing_forms = nil
routing_forms options: options
end

#
# Returns a list of activity log entries.
#
# @param [Hash] options the optional request parameters. Optional.
# @option options [Array<String>] :action The action(s) associated with the entries.
# @option options [Array<String>] :actor Return entries from the user(s) associated with the provided URIs.
# @option options [Integer] :count The number of rows to return.
# @option options [String] :max_occurred_at include entries that occurred prior to this time.
# @option options [String] :min_occurred_at Include entries that occurred after this time.
# @option options [Array<String>] :namespace The categories of the entries.
# @option options [String] :page_token The token to pass to get the next portion of the collection.
# @option options [String] :search_term Filters entries based on the search term.
# @option options [Array<String>] :sort Order results by the specified field and direction. List of {field}:{direction} values.
# @return [Array<Array<Calendly::ActivityLogEntry>, Hash, Hash>]
# - [Array<Calendly::ActivityLogEntry>] log_entries
# - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
# - [Hash] raw_response
# @raise [Calendly::Error] if the uri is empty.
# @raise [Calendly::ApiError] if the api returns error code.
# @since 0.14.0
def activity_log_entries(options: nil)
client.activity_log_entries uri, options: options
end
end
end
2 changes: 1 addition & 1 deletion lib/calendly/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Calendly
VERSION = '0.13.0'
VERSION = '0.14.0'
end
59 changes: 59 additions & 0 deletions test/assert_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,65 @@ def assert_no_show001(no_show)
assert_equal 'EV001', no_show.invitee.event.uuid
end

def assert_activity_log_entry001(log_entry)
assert log_entry.client.is_a? Calendly::Client
assert_equal 'ACTIVITY_LOG_ENTRY002', log_entry.id
assert_equal 'ACTIVITY_LOG_ENTRY002', log_entry.uuid
assert_equal 'https://api.calendly.com/activity_log_entries/ACTIVITY_LOG_ENTRY002', log_entry.uri
assert_equal Time.parse('2022-10-07T14:21:42.104549Z').to_i, log_entry.occurred_at.to_i
expected_actor = {
"uri": 'https://api.calendly.com/users/U001',
"type": 'User',
"organization": {
"uri": 'https://api.calendly.com/organizations/ORG001',
"role": 'owner'
},
"group": {
"uri": 'https://api.calendly.com/groups/GROUP001',
"name": 'Development',
"role": 'member'
},
"display_name": 'Sam Smith',
"alternative_identifier": 'sam.smith@gmail.com'
}
assert_equal expected_actor, log_entry.actor
expected_details = {
"name": 'test token'
}
assert_equal expected_details, log_entry.details
assert_equal 'API.Token_Created', log_entry.fully_qualified_name
assert_equal 'API', log_entry.namespace
assert_equal 'Token_Created', log_entry.action
assert_equal 'ORG001', log_entry.organization.uuid
end

def assert_activity_log_entry002(log_entry)
assert log_entry.client.is_a? Calendly::Client
assert_equal 'ACTIVITY_LOG_ENTRY001', log_entry.id
assert_equal 'ACTIVITY_LOG_ENTRY001', log_entry.uuid
assert_equal 'https://api.calendly.com/activity_log_entries/ACTIVITY_LOG_ENTRY001', log_entry.uri
assert_equal Time.parse('2022-09-26T13:41:43.915498Z').to_i, log_entry.occurred_at.to_i
expected_actor = {
"type": 'System',
"display_name": 'Calendly System'
}
assert_equal expected_actor, log_entry.actor
expected_details = {
"type": 'Invitee list',
"id": '893c514a-b6f7-4599-86f9-4273d16bfe43',
"emails": [
'alex.smith@gmail.com'
],
"requested_by": 'Sam Smith',
"uri": 'https://api.calendly.com/users/LOG001'
}
assert_equal expected_details, log_entry.details
assert_equal 'Compliance.Data_Deletion_Completed', log_entry.fully_qualified_name
assert_equal 'Compliance', log_entry.namespace
assert_equal 'Data_Deletion_Completed', log_entry.action
assert_equal 'ORG001', log_entry.organization.uuid
end

def assert_org_mem001(org_mem)
assert org_mem.client.is_a? Calendly::Client
assert_equal 'MEM001', org_mem.id
Expand Down
74 changes: 74 additions & 0 deletions test/client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,80 @@ def test_that_it_raises_an_argument_error_on_delete_invitee_data
assert_required_error proc_arg_is_empty, 'emails'
end

#
# test for activity_log_entries
#

def test_that_it_gets_activity_log_entries
org_uri = 'https://api.calendly.com/organizations/ORG001'
req_params = {organization: org_uri}
res_body = load_test_data 'activity_log_entries_001.json'

url = "#{HOST}/activity_log_entries?#{URI.encode_www_form(req_params)}"
add_stub_request :get, url, res_body: res_body

log_entries, next_page_token, raw_body = @client.activity_log_entries org_uri
assert_equal 2, log_entries.length
assert_activity_log_entry001 log_entries[0]
assert_activity_log_entry002 log_entries[1]
assert_nil next_page_token
assert_equal 2, raw_body[:total_count]
assert_equal false, raw_body[:exceeds_max_total_count]
assert_equal '2022-10-07T14:21:42Z', raw_body[:last_event_time]
end

def test_that_it_gets_activity_log_entries_with_full_options
org_uri = 'https://api.calendly.com/organizations/ORG001'
# setup options params
action = %w[Invite_Sent Succeeded]
actor = ['https://api.calendly.com/users/U001', 'https://api.calendly.com/users/U002']
count = 2
max_occurred_at = '2020-10-01T00:00:00Z'
min_occurred_at = '2022-08-01T00:00:00Z'
namespace = %w[Login User_Management]
page_token = 'NEXT_PAGE_TOKEN'
search_term = '*@other-website.com'
sort = ['occurred_at:asc', 'namespace:asc']
res_body = load_test_data 'activity_log_entries_001.json'
req_params = {
organization: org_uri,
'action[]': action,
'actor[]': actor,
count: count,
max_occurred_at: max_occurred_at,
min_occurred_at: min_occurred_at,
'namespace[]': namespace,
page_token: page_token,
search_term: search_term,
'sort[]': sort
}
url = "#{HOST}/activity_log_entries?#{URI.encode_www_form(req_params)}"
add_stub_request :get, url, res_body: res_body

options = {
action: action,
actor: actor,
count: count,
max_occurred_at: max_occurred_at,
min_occurred_at: min_occurred_at,
namespace: namespace,
page_token: page_token,
search_term: search_term,
sort: sort
}
log_entries, = @client.activity_log_entries org_uri, options: options
assert_equal 2, log_entries.length
assert_activity_log_entry001 log_entries[0]
assert_activity_log_entry002 log_entries[1]
end

def test_that_it_raises_an_argument_error_on_activity_log_entries
proc_arg_is_empty = proc do
@client.activity_log_entries nil
end
assert_required_error proc_arg_is_empty, 'org_uri'
end

#
# test for membership
#
Expand Down
21 changes: 21 additions & 0 deletions test/models/organization_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -330,5 +330,26 @@ def test_that_it_parses_uuid_be_formatted_ascii_from_uri
uri = "#{HOST}/organizations/#{uuid}"
assert_equal(uuid, Organization.extract_uuid(uri))
end

#
# test for activity_log_entries
#

def test_that_gets_it_activity_log_entries
req_params = {organization: @org_uri}
res_body = load_test_data 'activity_log_entries_001.json'

url = "#{HOST}/activity_log_entries?#{URI.encode_www_form(req_params)}"
add_stub_request :get, url, res_body: res_body

log_entries, next_page_token, raw_body = @org.activity_log_entries
assert_equal 2, log_entries.length
assert_activity_log_entry001 log_entries[0]
assert_activity_log_entry002 log_entries[1]
assert_nil next_page_token
assert_equal 2, raw_body[:total_count]
assert_equal false, raw_body[:exceeds_max_total_count]
assert_equal '2022-10-07T14:21:42Z', raw_body[:last_event_time]
end
end
end
61 changes: 61 additions & 0 deletions test/testdata/activity_log_entries_001.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"collection": [
{
"occurred_at": "2022-10-07T14:21:42.104549Z",
"actor": {
"uri": "https://api.calendly.com/users/U001",
"type": "User",
"organization": {
"uri": "https://api.calendly.com/organizations/ORG001",
"role": "owner"
},
"group": {
"uri": "https://api.calendly.com/groups/GROUP001",
"name": "Development",
"role": "member"
},
"display_name": "Sam Smith",
"alternative_identifier": "sam.smith@gmail.com"
},
"details": {
"name": "test token"
},
"organization": "https://api.calendly.com/organizations/ORG001",
"fully_qualified_name": "API.Token_Created",
"namespace": "API",
"action": "Token_Created",
"uri": "https://api.calendly.com/activity_log_entries/ACTIVITY_LOG_ENTRY002"
},
{
"occurred_at": "2022-09-26T13:41:43.915498Z",
"actor": {
"type": "System",
"display_name": "Calendly System"
},
"details": {
"type": "Invitee list",
"id": "893c514a-b6f7-4599-86f9-4273d16bfe43",
"emails": [
"alex.smith@gmail.com"
],
"requested_by": "Sam Smith",
"uri": "https://api.calendly.com/users/LOG001"
},
"organization": "https://api.calendly.com/organizations/ORG001",
"fully_qualified_name": "Compliance.Data_Deletion_Completed",
"namespace": "Compliance",
"action": "Data_Deletion_Completed",
"uri": "https://api.calendly.com/activity_log_entries/ACTIVITY_LOG_ENTRY001"
}
],
"pagination": {
"count": 20,
"next_page": null,
"next_page_token": null,
"previous_page": null,
"previous_page_token": null
},
"total_count": 2,
"exceeds_max_total_count": false,
"last_event_time": "2022-10-07T14:21:42Z"
}

0 comments on commit fcdb320

Please sign in to comment.