Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit 631ce9f

Browse files
v3: replace created_at query param with created_ats on audit_events
[ finishes #173574658] Co-authored-by: Reid Mitchell <rmitchell@pivotal.io> Co-authored-by: Merric de Launey <mdelauney@pivotal.io>
1 parent 2eba3fd commit 631ce9f

7 files changed

Lines changed: 53 additions & 61 deletions

File tree

app/fetchers/event_list_fetcher.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ def filter(message, dataset)
2828
dataset = dataset.where(organization_guid: message.organization_guids)
2929
end
3030

31-
if message.requested?(:created_at)
32-
if message.created_at.is_a?(Hash)
33-
operator = message.created_at.keys[0]
34-
given_timestamp = message.created_at.values[0]
31+
if message.requested?(:created_ats)
32+
if message.created_ats.is_a?(Hash)
33+
operator = message.created_ats.keys[0]
34+
given_timestamp = message.created_ats.values[0]
3535

3636
if operator == Event::LESS_THAN_COMPARATOR
3737
normalized_timestamp = Time.parse(given_timestamp).utc
@@ -53,7 +53,7 @@ def filter(message, dataset)
5353
# Gotcha: the equals operator returns all resources occurring within
5454
# the span of the second (e.g. "12:34:56.00-12:34:56.9999999"), for databases store
5555
# timestamps in sub-second accuracy (PostgreSQL stores in microseconds, for example)
56-
lower_bound = Time.parse(message.created_at).utc
56+
lower_bound = Time.parse(message.created_ats).utc
5757
upper_bound = Time.at(lower_bound + 0.99999).utc
5858
dataset = dataset.where(Sequel.lit('created_at BETWEEN ? AND ?', lower_bound, upper_bound))
5959
end

app/messages/events_list_message.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,34 @@ module VCAP::CloudController
44
class EventsListMessage < ListMessage
55
class CreatedAtValidator < ActiveModel::Validator
66
def validate(record)
7-
if record.requested?(:created_at)
8-
if record.created_at.is_a?(String)
9-
timestamp = record.created_at
7+
if record.requested?(:created_ats)
8+
if record.created_ats.is_a?(String)
9+
timestamp = record.created_ats
1010
else
11-
unless record.created_at.is_a?(Hash)
12-
record.errors[:created_at] << 'comparison operator and timestamp must be specified'
11+
unless record.created_ats.is_a?(Hash)
12+
record.errors[:created_ats] << 'comparison operator and timestamp must be specified'
1313
return
1414
end
1515

16-
comparison_operator = record.created_at.keys[0]
16+
comparison_operator = record.created_ats.keys[0]
1717
valid_comparision_operators = [
1818
Event::LESS_THAN_COMPARATOR,
1919
Event::GREATER_THAN_COMPARATOR,
2020
Event::LESS_THAN_OR_EQUAL_COMPARATOR,
2121
Event::GREATER_THAN_OR_EQUAL_COMPARATOR,
2222
]
2323
unless valid_comparision_operators.include?(comparison_operator)
24-
record.errors[:created_at] << "Invalid comparison operator: '#{comparison_operator}'"
24+
record.errors[:created_ats] << "Invalid comparison operator: '#{comparison_operator}'"
2525
end
2626

27-
timestamp = record.created_at.values[0]
27+
timestamp = record.created_ats.values[0]
2828
end
2929
begin
3030
raise ArgumentError.new('invalid date') unless timestamp =~ /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z\Z/
3131

3232
Time.iso8601(timestamp)
3333
rescue
34-
record.errors[:created_at] << "has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'"
34+
record.errors[:created_ats] << "has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'"
3535
return
3636
end
3737
end
@@ -43,7 +43,7 @@ def validate(record)
4343
:target_guids,
4444
:space_guids,
4545
:organization_guids,
46-
:created_at
46+
:created_ats
4747
]
4848

4949
validates_with NoAdditionalParamsValidator

docs/v3/source/includes/concepts/_filters.md.erb

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,13 @@ This will return all routes with hostname `"hostname1"`, `""` OR `"hostname2"`.
4141

4242
#### Relational Operators (Experimental)
4343

44-
##### Filtering on Equality
44+
Fields can be filtered using inequality when listing resources. Currently, this is supported only on
45+
the `created_at` field, using the `created_ats` filter.
4546

46-
Fields can be filtered using equality when listing resources. Currently, only the `created_at` field
47-
is supported. The `created_at` field expects a timestamp filter, and timestamps must be in ISO 8601
48-
format, e.g. `2020-06-30T12:34:56Z`.
49-
50-
##### Filtering on Inequality
51-
52-
Fields can be filtered using inequality when listing resources. Currently, only the `created_at`
53-
field is supported.
54-
55-
For example, a response to `/v3/audit_events?created_at[lt]=2020-06-30T12:34:56Z` will contain
47+
For example, a response to `/v3/audit_events?created_ats[lt]=2020-06-30T12:34:56Z` will contain
5648
audit events with a `created_at` timestamp strictly earlier than `2020-06-30T12:34:56Z`.
5749

58-
Timestamps must be in ISO 8601 format.
50+
Timestamps must be in [standard timestamp format](#timestamps).
5951

6052
##### Valid inequality operators
6153

docs/v3/source/includes/resources/audit_events/_list.md.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Retrieve all audit events the user has access to.
3030

3131
Name | Type | Description
3232
---- | ---- | ------------
33-
**created_at** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. Only supports relational operators, see [relational operators](#relational-operators-experimental)
33+
**created_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. Only supports relational operators, see [relational operators](#relational-operators-experimental)
3434
**types** | _list of strings_ | Comma-delimited list of event types to filter by
3535
**target_guids** | _list of strings_ | Comma-delimited list of target guids to filter by
3636
**space_guids** | _list of strings_ | Comma-delimited list of space guids to filter by

spec/request/events_spec.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
let!(:half_second_event) { VCAP::CloudController::Event.make(created_at: timestamp_half_second_later, organization_guid: org.guid, type: 'audit.organization.create') }
170170

171171
it 'returns events earlier than the given timestamp' do
172-
get "/v3/audit_events?created_at[lt]=#{timestamp}", nil, admin_header
172+
get "/v3/audit_events?created_ats[lt]=#{timestamp}", nil, admin_header
173173

174174
expect(
175175
resources: parsed_response['resources']
@@ -243,7 +243,7 @@
243243
end
244244

245245
it 'returns events earlier than the given timestamp' do
246-
get "/v3/audit_events?created_at[lte]=#{timestamp}", nil, admin_header
246+
get "/v3/audit_events?created_ats[lte]=#{timestamp}", nil, admin_header
247247

248248
expect(
249249
resources: parsed_response['resources']
@@ -286,7 +286,7 @@
286286
end
287287

288288
it 'returns events at or after the given timestamp' do
289-
get "/v3/audit_events?created_at[gte]=#{timestamp}", nil, admin_header
289+
get "/v3/audit_events?created_ats[gte]=#{timestamp}", nil, admin_header
290290

291291
expect(
292292
resources: parsed_response['resources']
@@ -298,7 +298,7 @@
298298

299299
context 'using greater than' do
300300
it 'returns events after the given timestamp' do
301-
get "/v3/audit_events?created_at[gt]=#{timestamp}", nil, admin_header
301+
get "/v3/audit_events?created_ats[gt]=#{timestamp}", nil, admin_header
302302

303303
expect(
304304
resources: parsed_response['resources']
@@ -341,7 +341,7 @@
341341
end
342342

343343
it 'returns events at the given timestamp' do
344-
get "/v3/audit_events?created_at=#{timestamp}", nil, admin_header
344+
get "/v3/audit_events?created_ats=#{timestamp}", nil, admin_header
345345

346346
expect(
347347
resources: parsed_response['resources']
@@ -353,7 +353,7 @@
353353

354354
context 'using an invalid operator' do
355355
it 'returns a useful error' do
356-
get "/v3/audit_events?created_at[goat]=#{timestamp}", nil, admin_header
356+
get "/v3/audit_events?created_ats[goat]=#{timestamp}", nil, admin_header
357357

358358
expect(last_response).to have_status_code(400)
359359
expect(last_response).to have_error_message("Invalid comparison operator: 'goat'")
@@ -363,22 +363,22 @@
363363
context 'using an invalid timestamp (with fractional seconds)' do
364364
let(:fractional_second_timestamp) { '2020-06-30T23:45:67.890Z' }
365365
it 'returns a useful error' do
366-
get "/v3/audit_events?created_at[lt]=#{fractional_second_timestamp}", nil, admin_header
366+
get "/v3/audit_events?created_ats[lt]=#{fractional_second_timestamp}", nil, admin_header
367367

368368
expect(last_response).to have_status_code(400)
369369
expect(last_response).to have_error_message(
370-
"The query parameter is invalid: Created at has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
370+
"The query parameter is invalid: Created ats has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
371371
end
372372
end
373373

374374
context 'using an invalid timestamp (local time zone)' do
375375
let(:local_timezone_timestamp) { '2020-06-30T23:45:67-0700' }
376376
it 'returns a useful error' do
377-
get "/v3/audit_events?created_at[lt]=#{local_timezone_timestamp}", nil, admin_header
377+
get "/v3/audit_events?created_ats[lt]=#{local_timezone_timestamp}", nil, admin_header
378378

379379
expect(last_response).to have_status_code(400)
380380
expect(last_response).to have_error_message(
381-
"The query parameter is invalid: Created at has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
381+
"The query parameter is invalid: Created ats has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
382382
end
383383
end
384384
end

spec/unit/fetchers/event_list_fetcher_spec.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ module VCAP::CloudController
7676

7777
context 'requesting events less than a timestamp' do
7878
let(:filters) do
79-
{ created_at: { lt: event_3.created_at.iso8601 } }
79+
{ created_ats: { lt: event_3.created_at.iso8601 } }
8080
end
8181

8282
it 'returns events with a created_at timestamp less than the given timestamp' do
@@ -94,7 +94,7 @@ module VCAP::CloudController
9494

9595
context 'requesting events less than or equal to a timestamp' do
9696
let(:filters) do
97-
{ created_at: { lte: event_3.created_at.iso8601 } }
97+
{ created_ats: { lte: event_3.created_at.iso8601 } }
9898
end
9999

100100
it 'returns events with a created_at timestamp before or at a given timestamp' do
@@ -112,7 +112,7 @@ module VCAP::CloudController
112112

113113
context 'requesting events greater than or equal to a timestamp' do
114114
let(:filters) do
115-
{ created_at: { gte: event_3.created_at.iso8601 } }
115+
{ created_ats: { gte: event_3.created_at.iso8601 } }
116116
end
117117

118118
it 'returns events with a created_at timestamp at or after a given timestamp' do
@@ -130,7 +130,7 @@ module VCAP::CloudController
130130

131131
context 'requesting events greater than a timestamp' do
132132
let(:filters) do
133-
{ created_at: { gt: event_3.created_at.iso8601 } }
133+
{ created_ats: { gt: event_3.created_at.iso8601 } }
134134
end
135135

136136
it 'returns events with a created_at timestamp greater than the given timestamp' do
@@ -148,7 +148,7 @@ module VCAP::CloudController
148148

149149
context 'requesting events equal to a timestamp' do
150150
let(:filters) do
151-
{ created_at: event_3.created_at.iso8601 }
151+
{ created_ats: event_3.created_at.iso8601 }
152152
end
153153

154154
it 'returns events with a created_at timestamp at or after a given timestamp' do

spec/unit/messages/events_list_message_spec.rb

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ module VCAP::CloudController
2727
target_guids: ['guid1', 'guid2'],
2828
space_guids: ['guid3', 'guid4'],
2929
organization_guids: ['guid5', 'guid6'],
30-
created_at: { lt: Time.now.utc.iso8601 },
30+
created_ats: { lt: Time.now.utc.iso8601 },
3131
})
3232
expect(message).to be_valid
3333
end
@@ -64,65 +64,65 @@ module VCAP::CloudController
6464
expect(message.errors[:organization_guids]).to include('must be an array')
6565
end
6666

67-
context 'validates the created_at filter' do
67+
context 'validates the created_ats filter' do
6868
it 'requires a hash or a timestamp' do
69-
message = EventsListMessage.from_params({ created_at: [Time.now.utc.iso8601] })
69+
message = EventsListMessage.from_params({ created_ats: [Time.now.utc.iso8601] })
7070
expect(message).not_to be_valid
71-
expect(message.errors[:created_at]).to include('comparison operator and timestamp must be specified')
71+
expect(message.errors[:created_ats]).to include('comparison operator and timestamp must be specified')
7272
end
7373

7474
it 'requires a valid comparison operator' do
75-
message = EventsListMessage.from_params({ created_at: { garbage: Time.now.utc.iso8601 } })
75+
message = EventsListMessage.from_params({ created_ats: { garbage: Time.now.utc.iso8601 } })
7676
expect(message).not_to be_valid
77-
expect(message.errors[:created_at]).to include("Invalid comparison operator: 'garbage'")
77+
expect(message.errors[:created_ats]).to include("Invalid comparison operator: 'garbage'")
7878
end
7979

8080
context 'requires a valid timestamp' do
8181
it "won't accept garbage" do
82-
message = EventsListMessage.from_params({ created_at: { gt: 123 } })
82+
message = EventsListMessage.from_params({ created_ats: { gt: 123 } })
8383
expect(message).not_to be_valid
84-
expect(message.errors[:created_at]).to include("has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
84+
expect(message.errors[:created_ats]).to include("has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
8585
end
8686
it "won't accept fractional seconds even though it's ISO 8601-compliant" do
87-
message = EventsListMessage.from_params({ created_at: { gt: '2020-06-30T12:34:56.78Z' } })
87+
message = EventsListMessage.from_params({ created_ats: { gt: '2020-06-30T12:34:56.78Z' } })
8888
expect(message).not_to be_valid
89-
expect(message.errors[:created_at]).to include("has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
89+
expect(message.errors[:created_ats]).to include("has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
9090
end
9191
it "won't accept local time zones even though it's ISO 8601-compliant" do
92-
message = EventsListMessage.from_params({ created_at: { gt: '2020-06-30T12:34:56.78-0700' } })
92+
message = EventsListMessage.from_params({ created_ats: { gt: '2020-06-30T12:34:56.78-0700' } })
9393
expect(message).not_to be_valid
94-
expect(message.errors[:created_at]).to include("has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
94+
expect(message.errors[:created_ats]).to include("has an invalid timestamp format. Timestamps should be formatted as 'YYYY-MM-DDThh:mm:ssZ'")
9595
end
9696
end
9797

9898
it 'allows the lt operator' do
99-
message = EventsListMessage.from_params({ created_at: { lt: Time.now.utc.iso8601 } })
99+
message = EventsListMessage.from_params({ created_ats: { lt: Time.now.utc.iso8601 } })
100100
expect(message).to be_valid
101101
end
102102

103103
it 'allows the lte operator' do
104-
message = EventsListMessage.from_params({ created_at: { lte: Time.now.utc.iso8601 } })
104+
message = EventsListMessage.from_params({ created_ats: { lte: Time.now.utc.iso8601 } })
105105
expect(message).to be_valid
106106
end
107107

108108
it 'allows the gt operator' do
109-
message = EventsListMessage.from_params({ created_at: { gt: Time.now.utc.iso8601 } })
109+
message = EventsListMessage.from_params({ created_ats: { gt: Time.now.utc.iso8601 } })
110110
expect(message).to be_valid
111111
end
112112

113113
it 'allows the gte operator' do
114-
message = EventsListMessage.from_params({ created_at: { gte: Time.now.utc.iso8601 } })
114+
message = EventsListMessage.from_params({ created_ats: { gte: Time.now.utc.iso8601 } })
115115
expect(message).to be_valid
116116
end
117117

118118
context 'when the operator is an equals operator' do
119119
it 'allows the equals operator' do
120-
message = EventsListMessage.from_params({ created_at: Time.now.utc.iso8601 })
120+
message = EventsListMessage.from_params({ created_ats: Time.now.utc.iso8601 })
121121
expect(message).to be_valid
122122
end
123123

124124
it 'errors on invalid (non-ISO 8601) timestamps' do
125-
message = EventsListMessage.from_params({ created_at: 'yesterday' })
125+
message = EventsListMessage.from_params({ created_ats: 'yesterday' })
126126
expect(message).to be_invalid
127127
end
128128
end

0 commit comments

Comments
 (0)