flapjack 0.8.10 → 0.8.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|