flapjack 0.8.10 → 0.8.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -1
- data/bin/flapjack +10 -1
- data/bin/flapjack-nagios-receiver +1 -2
- data/bin/simulate-failed-check +12 -4
- data/etc/flapjack_config.yaml.example +2 -1
- data/flapjack.gemspec +1 -0
- data/lib/flapjack/data/contact.rb +46 -26
- data/lib/flapjack/data/entity.rb +28 -0
- data/lib/flapjack/data/entity_check.rb +52 -11
- data/lib/flapjack/data/event.rb +9 -3
- data/lib/flapjack/data/notification_rule.rb +8 -0
- data/lib/flapjack/gateways/api.rb +0 -1
- data/lib/flapjack/gateways/api/entity_check_presenter.rb +2 -1
- data/lib/flapjack/gateways/email.rb +1 -2
- data/lib/flapjack/gateways/jabber.rb +3 -3
- data/lib/flapjack/gateways/jsonapi.rb +186 -38
- data/lib/flapjack/gateways/jsonapi/check_methods.rb +120 -0
- data/lib/flapjack/gateways/jsonapi/{entity_check_presenter.rb → check_presenter.rb} +7 -6
- data/lib/flapjack/gateways/jsonapi/contact_methods.rb +61 -352
- data/lib/flapjack/gateways/jsonapi/entity_methods.rb +117 -248
- data/lib/flapjack/gateways/jsonapi/medium_methods.rb +179 -0
- data/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb +124 -0
- data/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +128 -0
- data/lib/flapjack/gateways/jsonapi/rack/json_params_parser.rb +4 -5
- data/lib/flapjack/gateways/jsonapi/report_methods.rb +143 -0
- data/lib/flapjack/gateways/web.rb +1 -0
- data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +165 -101
- data/lib/flapjack/gateways/web/public/js/contacts.js +34 -46
- data/lib/flapjack/gateways/web/public/js/select2.js +232 -90
- data/lib/flapjack/gateways/web/public/js/select2.min.js +4 -4
- data/lib/flapjack/gateways/web/views/check.html.erb +11 -2
- data/lib/flapjack/processor.rb +6 -6
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/data/entity_check_spec.rb +1 -1
- data/spec/lib/flapjack/data/event_spec.rb +10 -9
- data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +25 -25
- data/spec/lib/flapjack/gateways/api_spec.rb +23 -1
- data/spec/lib/flapjack/gateways/email_spec.rb +40 -2
- data/spec/lib/flapjack/gateways/jabber_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +134 -0
- data/spec/lib/flapjack/gateways/jsonapi/{entity_check_presenter_spec.rb → check_presenter_spec.rb} +17 -17
- data/spec/lib/flapjack/gateways/jsonapi/contact_methods_spec.rb +27 -232
- data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +217 -687
- data/spec/lib/flapjack/gateways/jsonapi/medium_methods_spec.rb +232 -0
- data/spec/lib/flapjack/gateways/jsonapi/notification_rule_methods_spec.rb +131 -0
- data/spec/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods_spec.rb +113 -0
- data/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb +546 -0
- data/spec/lib/flapjack/gateways/jsonapi_spec.rb +10 -1
- data/spec/lib/flapjack/gateways/web_spec.rb +1 -0
- data/spec/support/jsonapi_helper.rb +62 -0
- metadata +36 -8
- data/lib/flapjack/gateways/jsonapi/entity_presenter.rb +0 -75
- data/spec/lib/flapjack/gateways/jsonapi/entity_presenter_spec.rb +0 -108
@@ -5,9 +5,6 @@ require 'sinatra/base'
|
|
5
5
|
require 'flapjack/data/entity'
|
6
6
|
require 'flapjack/data/entity_check'
|
7
7
|
|
8
|
-
require 'flapjack/gateways/jsonapi/entity_presenter'
|
9
|
-
require 'flapjack/gateways/jsonapi/entity_check_presenter'
|
10
|
-
|
11
8
|
module Flapjack
|
12
9
|
|
13
10
|
module Gateways
|
@@ -18,297 +15,169 @@ module Flapjack
|
|
18
15
|
|
19
16
|
module Helpers
|
20
17
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
|
29
|
-
check, :redis => redis)
|
30
|
-
raise Flapjack::Gateways::JSONAPI::EntityCheckNotFound.new(entity, check) if entity_check.nil?
|
31
|
-
entity_check
|
32
|
-
end
|
33
|
-
|
34
|
-
def find_tags(tags)
|
35
|
-
halt err(403, "no tags") if tags.nil? || tags.empty?
|
36
|
-
tags
|
37
|
-
end
|
38
|
-
|
39
|
-
def entities_and_checks(entity_name, check)
|
40
|
-
if entity_name
|
41
|
-
# backwards-compatible, single entity or entity&check from route
|
42
|
-
entities = check ? nil : [entity_name]
|
43
|
-
checks = check ? {entity_name => check} : nil
|
44
|
-
else
|
45
|
-
# new and improved bulk API queries
|
46
|
-
entities = params[:entity]
|
47
|
-
checks = params[:check]
|
48
|
-
entities = [entities] unless entities.nil? || entities.is_a?(Array)
|
49
|
-
# TODO err if checks isn't a Hash (similar rules as in flapjack-diner)
|
50
|
-
end
|
51
|
-
[entities, checks]
|
52
|
-
end
|
53
|
-
|
54
|
-
def bulk_api_check_action(entities, entity_checks, action, params = {})
|
55
|
-
unless entities.nil? || entities.empty?
|
56
|
-
entities.each do |entity_name|
|
57
|
-
entity = find_entity(entity_name)
|
58
|
-
checks = entity.check_list.sort
|
59
|
-
checks.each do |check|
|
60
|
-
action.call( find_entity_check(entity, check) )
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
unless entity_checks.nil? || entity_checks.empty?
|
66
|
-
entity_checks.each_pair do |entity_name, checks|
|
67
|
-
entity = find_entity(entity_name)
|
68
|
-
checks = [checks] unless checks.is_a?(Array)
|
69
|
-
checks.each do |check|
|
70
|
-
action.call( find_entity_check(entity, check) )
|
71
|
-
end
|
18
|
+
def checks_for_entity_ids(entity_ids)
|
19
|
+
return if entity_ids.nil?
|
20
|
+
entity_ids.inject([]) do |memo, entity_id|
|
21
|
+
entity = find_entity_by_id(entity_id)
|
22
|
+
check_names = entity.check_list.sort
|
23
|
+
check_names.each do |check_name|
|
24
|
+
memo << find_entity_check(entity, check_name)
|
72
25
|
end
|
26
|
+
memo
|
73
27
|
end
|
74
28
|
end
|
29
|
+
end
|
75
30
|
|
76
|
-
|
77
|
-
|
31
|
+
def self.registered(app)
|
32
|
+
app.helpers Flapjack::Gateways::JSONAPI::Helpers
|
33
|
+
app.helpers Flapjack::Gateways::JSONAPI::EntityMethods::Helpers
|
78
34
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
35
|
+
# Returns all (/entities) or some (/entities/A,B,C) or one (/entities/A) contact(s)
|
36
|
+
# NB: only works with good data -- i.e. entity must have an id
|
37
|
+
app.get %r{^/entities(?:/)?([^/]+)?$} do
|
38
|
+
requested_entities = if params[:captures] && params[:captures][0]
|
39
|
+
params[:captures][0].split(',').uniq
|
40
|
+
else
|
41
|
+
nil
|
84
42
|
end
|
85
43
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
memo += checks.collect {|check|
|
91
|
-
entity_check = find_entity_check(entity, check)
|
92
|
-
{:entity => entity_name,
|
93
|
-
:check => check,
|
94
|
-
result_type.to_sym => yield(Flapjack::Gateways::JSONAPI::EntityCheckPresenter.new(entity_check))
|
95
|
-
}
|
96
|
-
}
|
97
|
-
}.flatten(1)
|
44
|
+
entities = if requested_entities
|
45
|
+
Flapjack::Data::Entity.find_by_ids(requested_entities, :logger => logger, :redis => redis)
|
46
|
+
else
|
47
|
+
Flapjack::Data::Entity.all(:redis => redis)
|
98
48
|
end
|
49
|
+
entities.compact!
|
99
50
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
# NB: casts to UTC before converting to a timestamp
|
104
|
-
def validate_and_parsetime(value)
|
105
|
-
return unless value
|
106
|
-
Time.iso8601(value).getutc.to_i
|
107
|
-
rescue ArgumentError => e
|
108
|
-
logger.error "Couldn't parse time from '#{value}'"
|
109
|
-
nil
|
110
|
-
end
|
111
|
-
|
112
|
-
end
|
113
|
-
|
114
|
-
# used for backwards-compatible route matching below
|
115
|
-
ENTITY_CHECK_FRAGMENT = '(?:/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(.+))?)?'
|
116
|
-
|
117
|
-
def self.registered(app)
|
118
|
-
|
119
|
-
app.helpers Flapjack::Gateways::JSONAPI::EntityMethods::Helpers
|
51
|
+
if requested_entities && requested_entities.empty?
|
52
|
+
raise Flapjack::Gateways::JSONAPI::EntitiesNotFound.new(requested_entities)
|
53
|
+
end
|
120
54
|
|
121
|
-
|
122
|
-
content_type :json
|
123
|
-
cors_headers
|
55
|
+
linked_contact_ids = Flapjack::Data::Entity.contact_ids_for(entities.map(&:id), :redis => redis)
|
124
56
|
|
125
|
-
entities_json =
|
126
|
-
|
127
|
-
|
128
|
-
{'id' => id, 'name' => e.name, 'checks' => presenter.status }.to_json
|
129
|
-
}.join(',')
|
57
|
+
entities_json = entities.collect {|entity|
|
58
|
+
entity.to_jsonapi(:contact_ids => linked_contact_ids[entity.id])
|
59
|
+
}.join(",")
|
130
60
|
|
131
61
|
'{"entities":[' + entities_json + ']}'
|
132
62
|
end
|
133
63
|
|
64
|
+
app.post '/entities' do
|
65
|
+
entities = wrapped_params('entities')
|
66
|
+
return err(403, "Entity with a nil id detected") if entities.any? {|e| e['id'].nil?}
|
134
67
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
captures = params[:captures] || []
|
139
|
-
entity_name = captures[0]
|
140
|
-
check = captures[1]
|
141
|
-
|
142
|
-
entities, checks = entities_and_checks(entity_name, check)
|
143
|
-
|
144
|
-
results = present_api_results(entities, checks, 'status') {|presenter|
|
145
|
-
presenter.status
|
68
|
+
entity_ids = entities.collect{|entity_data|
|
69
|
+
Flapjack::Data::Entity.add(entity_data, :redis => redis)
|
70
|
+
entity_data['id']
|
146
71
|
}
|
147
72
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
check ? results.first.to_json : "[" + results.map {|r| r.to_json }.join(',') + "]"
|
152
|
-
else
|
153
|
-
# new and improved data format which reflects the request param structure
|
154
|
-
"[" + results.map {|r| r.to_json }.join(',') + "]"
|
155
|
-
end
|
73
|
+
response.headers['Location'] = "#{request.base_url}/entities/#{entity_ids.join(',')}"
|
74
|
+
status 201
|
75
|
+
entity_ids.to_json
|
156
76
|
end
|
157
77
|
|
158
|
-
app.
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
results = present_api_results(entities, checks, action) {|presenter|
|
169
|
-
presenter.send(action, start_time, end_time)
|
170
|
-
}
|
171
|
-
|
172
|
-
if check
|
173
|
-
# compatible with previous data format
|
174
|
-
results.first[action].to_json
|
175
|
-
elsif entity_name
|
176
|
-
# compatible with previous data format
|
177
|
-
rename = {:unscheduled_maintenances => :unscheduled_maintenance,
|
178
|
-
:scheduled_maintenances => :scheduled_maintenance}
|
179
|
-
drop = [:entity]
|
180
|
-
results.collect{|r|
|
181
|
-
r.inject({}) {|memo, (k, v)|
|
182
|
-
if new_k = rename[k]
|
183
|
-
memo[new_k] = v
|
184
|
-
elsif !drop.include?(k)
|
185
|
-
memo[k] = v
|
78
|
+
app.patch '/entities/:id' do
|
79
|
+
params[:id].split(',').collect {|entity_id|
|
80
|
+
find_entity_by_id(entity_id)
|
81
|
+
}.each do |entity|
|
82
|
+
apply_json_patch('entities') do |op, property, linked, value|
|
83
|
+
case op
|
84
|
+
when 'replace'
|
85
|
+
if ['name'].include?(property)
|
86
|
+
# # Name change not supported in Flapjack v1.x, too many changes required
|
87
|
+
# entity.update(property => value)
|
186
88
|
end
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
89
|
+
when 'add'
|
90
|
+
if 'contacts'.eql?(linked)
|
91
|
+
contact = Flapjack::Data::Contact.find_by_id(value, :redis => redis)
|
92
|
+
contact.add_entity(entity) unless contact.nil?
|
93
|
+
end
|
94
|
+
when 'remove'
|
95
|
+
if 'contacts'.eql?(linked)
|
96
|
+
contact = Flapjack::Data::Contact.find_by_id(value, :redis => redis)
|
97
|
+
contact.remove_entity(entity) unless contact.nil?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
193
101
|
end
|
102
|
+
|
103
|
+
status 204
|
194
104
|
end
|
195
105
|
|
196
106
|
# create a scheduled maintenance period for a check on an entity
|
197
|
-
app.post %r{/
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
act_proc = proc {|entity_check|
|
209
|
-
entity_check.create_scheduled_maintenance(start_time,
|
210
|
-
params[:duration].to_i, :summary => params[:summary])
|
211
|
-
}
|
107
|
+
app.post %r{^/scheduled_maintenances/entities/([^/]+)$} do
|
108
|
+
scheduled_maintenances = wrapped_params('scheduled_maintenances')
|
109
|
+
checks_for_entity_ids(params[:captures][0].split(',')).each do |check|
|
110
|
+
scheduled_maintenances.each do |wp|
|
111
|
+
start_time = validate_and_parsetime(wp['start_time'])
|
112
|
+
halt( err(403, "start time must be provided") ) unless start_time
|
113
|
+
check.create_scheduled_maintenance(start_time,
|
114
|
+
wp['duration'].to_i, :summary => wp['summary'])
|
115
|
+
end
|
116
|
+
end
|
212
117
|
|
213
|
-
bulk_api_check_action(entities, checks, act_proc)
|
214
118
|
status 204
|
215
119
|
end
|
216
120
|
|
217
121
|
# create an acknowledgement for a service on an entity
|
218
122
|
# NB currently, this does not acknowledge a specific failure event, just
|
219
123
|
# the entity-check as a whole
|
220
|
-
app.post %r{/
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
Flapjack::Data::Event.create_acknowledgement(
|
236
|
-
entity_check.entity_name, entity_check.check,
|
237
|
-
:summary => params[:summary],
|
238
|
-
:duration => duration,
|
239
|
-
:redis => redis)
|
240
|
-
}
|
124
|
+
app.post %r{^/unscheduled_maintenances/entities/([^/]+)$} do
|
125
|
+
unscheduled_maintenances = wrapped_params('unscheduled_maintenances', false)
|
126
|
+
checks_for_entity_ids(params[:captures][0].split(',')).each do |check|
|
127
|
+
unscheduled_maintenances.each do |wp|
|
128
|
+
dur = wp['duration'] ? wp['duration'].to_i : nil
|
129
|
+
duration = (dur.nil? || (dur <= 0)) ? (4 * 60 * 60) : dur
|
130
|
+
summary = wp['summary']
|
131
|
+
|
132
|
+
opts = {:duration => duration}
|
133
|
+
opts[:summary] = summary if summary
|
134
|
+
|
135
|
+
Flapjack::Data::Event.create_acknowledgement(
|
136
|
+
check.entity_name, check.check, {:redis => redis}.merge(opts))
|
137
|
+
end
|
138
|
+
end
|
241
139
|
|
242
|
-
bulk_api_check_action(entities, checks, act_proc)
|
243
140
|
status 204
|
244
141
|
end
|
245
142
|
|
246
|
-
app.
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
proc {|entity_check| entity_check.end_scheduled_maintenance(start_time.to_i) }
|
258
|
-
when 'unscheduled_maintenances'
|
259
|
-
end_time = validate_and_parsetime(params[:end_time]) || Time.now
|
260
|
-
proc {|entity_check| entity_check.end_unscheduled_maintenance(end_time.to_i) }
|
143
|
+
app.patch %r{^/unscheduled_maintenances/entities/([^/]+)$} do
|
144
|
+
checks_for_entity_ids( params[:captures][0].split(',') ).each do |check|
|
145
|
+
apply_json_patch('unscheduled_maintenances') do |op, property, linked, value|
|
146
|
+
case op
|
147
|
+
when 'replace'
|
148
|
+
if ['end_time'].include?(property)
|
149
|
+
end_time = validate_and_parsetime(value)
|
150
|
+
check.end_unscheduled_maintenance(end_time.to_i)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
261
154
|
end
|
262
|
-
|
263
|
-
bulk_api_check_action(entities, checks, act_proc)
|
264
155
|
status 204
|
265
156
|
end
|
266
157
|
|
267
|
-
app.
|
268
|
-
|
269
|
-
|
270
|
-
check = captures[1]
|
271
|
-
|
272
|
-
entities, checks = entities_and_checks(entity_name, check)
|
273
|
-
|
274
|
-
act_proc = proc {|entity_check|
|
275
|
-
summary = params[:summary] ||
|
276
|
-
"Testing notifications to all contacts interested in entity #{entity_check.entity.name}"
|
277
|
-
Flapjack::Data::Event.test_notifications(
|
278
|
-
entity_check.entity_name, entity_check.check,
|
279
|
-
:summary => summary,
|
280
|
-
:redis => redis)
|
281
|
-
}
|
158
|
+
app.delete %r{^/scheduled_maintenances/entities/([^/]+)$} do
|
159
|
+
start_time = validate_and_parsetime(params[:start_time])
|
160
|
+
halt( err(403, "start time must be provided") ) unless start_time
|
282
161
|
|
283
|
-
|
162
|
+
checks_for_entity_ids(params[:captures][0].split(',')).each do |check|
|
163
|
+
check.end_scheduled_maintenance(start_time.to_i)
|
164
|
+
end
|
284
165
|
status 204
|
285
166
|
end
|
286
167
|
|
287
|
-
app.post
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
logger.debug("no entities object found in the following supplied JSON:")
|
298
|
-
logger.debug(request.body)
|
299
|
-
return err(403, "No entities object received")
|
300
|
-
end
|
301
|
-
return err(403, "The received entities object is not an Enumerable") unless entities.is_a?(Enumerable)
|
302
|
-
return err(403, "Entity with a nil id detected") unless entities.any? {|e| !e['id'].nil?}
|
303
|
-
|
304
|
-
entities.each do |entity|
|
305
|
-
unless entity['id']
|
306
|
-
errors << "Entity not imported as it has no id: #{entity.inspect}"
|
307
|
-
next
|
168
|
+
app.post %r{^/test_notifications/entities/([^/]+)$} do
|
169
|
+
test_notifications = wrapped_params('test_notifications', false)
|
170
|
+
checks_for_entity_ids(params[:captures][0].split(',')).each do |check|
|
171
|
+
test_notifications.each do |wp|
|
172
|
+
summary = wp['summary'] ||
|
173
|
+
"Testing notifications to all contacts interested in entity #{check.entity.name}"
|
174
|
+
Flapjack::Data::Event.test_notifications(
|
175
|
+
check.entity_name, check.check,
|
176
|
+
:summary => summary,
|
177
|
+
:redis => redis)
|
308
178
|
end
|
309
|
-
Flapjack::Data::Entity.add(entity, :redis => redis)
|
310
179
|
end
|
311
|
-
|
180
|
+
status 204
|
312
181
|
end
|
313
182
|
|
314
183
|
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'sinatra/base'
|
4
|
+
|
5
|
+
require 'flapjack/data/contact'
|
6
|
+
|
7
|
+
module Flapjack
|
8
|
+
|
9
|
+
module Gateways
|
10
|
+
|
11
|
+
class JSONAPI < Sinatra::Base
|
12
|
+
|
13
|
+
module MediumMethods
|
14
|
+
|
15
|
+
SEMAPHORE_CONTACT_MASS_UPDATE = 'contact_mass_update'
|
16
|
+
|
17
|
+
module Helpers
|
18
|
+
|
19
|
+
def obtain_semaphore(resource)
|
20
|
+
semaphore = nil
|
21
|
+
strikes = 0
|
22
|
+
begin
|
23
|
+
semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 30)
|
24
|
+
rescue Flapjack::Data::Semaphore::ResourceLocked
|
25
|
+
strikes += 1
|
26
|
+
raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) unless strikes < 3
|
27
|
+
sleep 1
|
28
|
+
retry
|
29
|
+
end
|
30
|
+
raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) unless semaphore
|
31
|
+
semaphore
|
32
|
+
end
|
33
|
+
|
34
|
+
# TODO validate that media type exists in redis
|
35
|
+
def split_media_ids(media_ids)
|
36
|
+
|
37
|
+
contact_cache = {}
|
38
|
+
|
39
|
+
media_ids.split(',').uniq.collect do |m_id|
|
40
|
+
m_id =~ /\A(.+)_(email|sms|jabber)\z/
|
41
|
+
|
42
|
+
contact_id = $1
|
43
|
+
media_type = $2
|
44
|
+
halt err(422, "Could not get contact_id from media_id") if contact_id.nil?
|
45
|
+
halt err(422, "Could not get media type from media_id") if media_type.nil?
|
46
|
+
|
47
|
+
contact_cache[contact_id] ||= find_contact(contact_id)
|
48
|
+
|
49
|
+
{:contact => contact_cache[contact_id], :type => media_type}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.registered(app)
|
56
|
+
app.helpers Flapjack::Gateways::JSONAPI::Helpers
|
57
|
+
app.helpers Flapjack::Gateways::JSONAPI::MediumMethods::Helpers
|
58
|
+
|
59
|
+
# Creates media records for a contact
|
60
|
+
app.post '/contacts/:contact_id/media' do
|
61
|
+
media_data = params[:media]
|
62
|
+
|
63
|
+
if media_data.nil? || !media_data.is_a?(Enumerable)
|
64
|
+
halt err(422, "No valid media were submitted")
|
65
|
+
end
|
66
|
+
|
67
|
+
unless media_data.all? {|m| m['id'].nil? }
|
68
|
+
halt err(422, "Media creation cannot include IDs")
|
69
|
+
end
|
70
|
+
|
71
|
+
semaphore = obtain_semaphore(SEMAPHORE_CONTACT_MASS_UPDATE)
|
72
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
73
|
+
if contact.nil?
|
74
|
+
semaphore.release
|
75
|
+
halt err(422, "Contact id:'#{params[:contact_id]}' could not be loaded")
|
76
|
+
end
|
77
|
+
|
78
|
+
media_data.each do |medium_data|
|
79
|
+
type = medium_data['type']
|
80
|
+
contact.set_address_for_media(type, medium_data['address'])
|
81
|
+
contact.set_interval_for_media(type, medium_data['interval'])
|
82
|
+
contact.set_rollup_threshold_for_media(type, medium_data['rollup_threshold'])
|
83
|
+
medium_data[:id] = "#{contact.id}_#{type}"
|
84
|
+
medium_data[:links] = {:contacts => [contact.id]}
|
85
|
+
end
|
86
|
+
|
87
|
+
semaphore.release
|
88
|
+
|
89
|
+
status 201
|
90
|
+
|
91
|
+
'{"media":' + media_data.to_json + '}'
|
92
|
+
end
|
93
|
+
|
94
|
+
# get one or more media records; media ids are, for Flapjack
|
95
|
+
# v1, composed of "#{contact.id}_#{media_type}"
|
96
|
+
app.get %r{^/media(?:/)?([^/]+)?$} do
|
97
|
+
media_list_cache = {}
|
98
|
+
contact_media = if params[:captures] && params[:captures][0]
|
99
|
+
split_media_ids(params[:captures][0])
|
100
|
+
else
|
101
|
+
Flapjack::Data::Contact.all(:redis => redis).collect do |contact|
|
102
|
+
media_list_cache[contact.id] ||= contact.media_list
|
103
|
+
media_list_cache[contact.id].collect do |media_type|
|
104
|
+
{:contact => contact, :type => media_type}
|
105
|
+
end
|
106
|
+
end.flatten(1)
|
107
|
+
end
|
108
|
+
|
109
|
+
media_data = contact_media.inject([]) do |memo, contact_media_type|
|
110
|
+
contact = contact_media_type[:contact]
|
111
|
+
media_type = contact_media_type[:type]
|
112
|
+
|
113
|
+
media_list_cache[contact.id] ||= contact.media_list
|
114
|
+
if media_list_cache[contact.id].include?(media_type)
|
115
|
+
medium_id = "#{contact.id}_#{media_type}"
|
116
|
+
memo <<
|
117
|
+
{:id => medium_id,
|
118
|
+
:type => media_type,
|
119
|
+
:address => contact.media[media_type],
|
120
|
+
:interval => contact.media_intervals[media_type],
|
121
|
+
:rollup_threshold => contact.media_rollup_thresholds[media_type],
|
122
|
+
:links => {:contacts => [contact.id]}}
|
123
|
+
end
|
124
|
+
|
125
|
+
memo
|
126
|
+
end
|
127
|
+
|
128
|
+
'{"media":' + media_data.to_json + '}'
|
129
|
+
end
|
130
|
+
|
131
|
+
# update one or more media records; media ids are, for Flapjack
|
132
|
+
# v1, composed of "#{contact.id}_#{media_type}"
|
133
|
+
app.patch '/media/:id' do
|
134
|
+
media_list_cache = {}
|
135
|
+
split_media_ids(params[:id]).each do |contact_media_type|
|
136
|
+
contact = contact_media_type[:contact]
|
137
|
+
media_type = contact_media_type[:type]
|
138
|
+
media_list_cache[contact.id] ||= contact.media_list
|
139
|
+
next unless media_list_cache[contact.id].include?(media_type)
|
140
|
+
apply_json_patch('media') do |op, property, linked, value|
|
141
|
+
if 'replace'.eql?(op)
|
142
|
+
case property
|
143
|
+
when 'address'
|
144
|
+
contact.set_address_for_media(media_type, value)
|
145
|
+
when 'interval'
|
146
|
+
contact.set_interval_for_media(media_type, value)
|
147
|
+
when 'rollup_threshold'
|
148
|
+
contact.set_rollup_threshold_for_media(media_type, value)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
status 204
|
155
|
+
end
|
156
|
+
|
157
|
+
# delete one or more media records; media ids are, for Flapjack
|
158
|
+
# v1, composed of "#{contact.id}_#{media_type}"
|
159
|
+
app.delete '/media/:id' do
|
160
|
+
media_list_cache = {}
|
161
|
+
split_media_ids(params[:id]).each do |contact_media_type|
|
162
|
+
contact = contact_media_type[:contact]
|
163
|
+
media_type = contact_media_type[:type]
|
164
|
+
media_list_cache[contact.id] ||= contact.media_list
|
165
|
+
next unless media_list_cache[contact.id].include?(media_type)
|
166
|
+
contact.remove_media(media_type)
|
167
|
+
end
|
168
|
+
status 204
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|