model_driven_api 3.7.4 → 3.8.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1053d8f7e666ab9eb65f47714e9a02881028b261b10e4667b24ca8a4883eb45
4
- data.tar.gz: d106be5cfe8eaff72ef75a9dfe910014af157f1726540197f97bc7d37b07993a
3
+ metadata.gz: 1f0f44e2c1015c731953af0fd3f2e05128e5e8d2493775a7788bd8ecab306f49
4
+ data.tar.gz: 2fd0bb9b281db660563a58890d7c287e5589043e32e5d5b1b30a828b6103f563
5
5
  SHA512:
6
- metadata.gz: d970bb7e8bb28e5c04e03e35d2528b916d121741ee570c3fdd838f86b365f9a584147f5da9f7240e8e9444fe755632a09c452c1e3e25163746647f4d0d9c0f8b
7
- data.tar.gz: 49d4d7cf759bc034dd48d43e006e277f356c0512e876843329bbf67856f82fbd19e26aa5b50633585c2548523123a007451fcd36364d379709350a314988356c
6
+ metadata.gz: 5498cd511a63b1a8ac368015b4e10786518a80d030aa9b9c93656a1870bda7c677076559e3b1061fec1a557dcab9faecc77a064b4b250f52598b1249dade435c
7
+ data.tar.gz: d3d2be5de0a1a2cc35a7db37b9cee0d8eaf8dbcb594e7b557bccda62354df909ba4258b70e9dd59f03ded31b73631a288e1acbdb1d0bd07c106847867cab7f8d
@@ -57,30 +57,45 @@ class Endpoints::PushSubscriber < NonCrudEndpoints
57
57
 
58
58
  self.desc 'PushSubscriber', :send_push, {
59
59
  post: {
60
- summary: 'Send a Web Push notification to a specific subscriber',
60
+ summary: 'Send Web Push to one subscriber (push_subscriber_id) or many (push_subscriber_ids array, async).',
61
61
  parameters: [],
62
62
  responses: {
63
- '201' => { description: 'Message created and dispatched' },
63
+ '201' => { description: 'Single: message JSON. Bulk: { created: [...], failed: [...] }' },
64
64
  '422' => { description: 'Validation error' },
65
- '404' => { description: 'Subscriber not found' }
65
+ '404' => { description: 'Subscriber not found (single mode only)' }
66
66
  }
67
67
  }
68
68
  }
69
69
 
70
70
  def send_push(params)
71
- subscriber = PushSubscriber.active.find_by(id: params[:push_subscriber_id])
72
- return [{ error: 'Subscriber not found' }, 404] unless subscriber
73
- message = subscriber.push_messages.build(
74
- title: params[:title],
75
- body: params[:body],
76
- url: params[:url],
77
- icon: params[:icon]
78
- )
79
- unless message.save
80
- return [{ error: message.errors.full_messages.join(', ') }, 422]
71
+ return [{ error: 'title is required' }, 422] if params[:title].blank?
72
+ return [{ error: 'body is required' }, 422] if params[:body].blank?
73
+
74
+ if params[:push_subscriber_ids].present?
75
+ send_push_bulk(params)
76
+ else
77
+ send_push_single(params)
81
78
  end
82
- ThecoreBackendCommons::PushNotificationService.dispatch(subscriber, message)
83
- [message, 201]
79
+ rescue => e
80
+ [{ error: e.message }, 500]
81
+ end
82
+
83
+ self.desc 'PushSubscriber', :broadcast_push, {
84
+ post: {
85
+ summary: 'Send Web Push to all active subscribers.',
86
+ parameters: [],
87
+ responses: {
88
+ '201' => { description: '{ enqueued: N } — number of jobs enqueued' },
89
+ '422' => { description: 'Validation error (title or body missing)' }
90
+ }
91
+ }
92
+ }
93
+
94
+ def broadcast_push(params)
95
+ return [{ error: 'title is required' }, 422] if params[:title].blank?
96
+ return [{ error: 'body is required' }, 422] if params[:body].blank?
97
+
98
+ broadcast_push_all(params)
84
99
  rescue => e
85
100
  [{ error: e.message }, 500]
86
101
  end
@@ -103,8 +118,89 @@ class Endpoints::PushSubscriber < NonCrudEndpoints
103
118
  now = Time.current
104
119
  message.update!(received_at: now) if params[:received] && message.received_at.nil?
105
120
  message.update!(read_at: now) if params[:read] && message.read_at.nil?
106
- [message, 200]
121
+ [message.as_json(PushMessage.json_attrs), 200]
107
122
  rescue ActiveRecord::RecordInvalid => e
108
123
  [{ error: e.message }, 422]
109
124
  end
125
+
126
+ private
127
+
128
+ def send_push_single(params) # rubocop:disable Metrics/MethodLength
129
+ subscriber = PushSubscriber.active.find_by(id: params[:push_subscriber_id])
130
+ return [{ error: 'Subscriber not found' }, 404] unless subscriber
131
+
132
+ message = subscriber.push_messages.build(
133
+ title: params[:title],
134
+ body: params[:body],
135
+ url: params[:url],
136
+ icon: params[:icon]
137
+ )
138
+ return [{ error: message.errors.full_messages.join(', ') }, 422] unless message.save
139
+
140
+ ThecoreBackendCommons::PushNotificationService.dispatch(subscriber, message)
141
+ [message.as_json(PushMessage.json_attrs), 201]
142
+ end
143
+
144
+ def broadcast_push_all(params) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
145
+ active_ids = PushSubscriber.active.pluck(:id)
146
+ return [{ enqueued: 0 }, 201] if active_ids.empty?
147
+
148
+ now = Time.current
149
+ records = active_ids.map do |sub_id|
150
+ {
151
+ push_subscriber_id: sub_id,
152
+ title: params[:title],
153
+ body: params[:body],
154
+ url: params[:url].presence,
155
+ icon: params[:icon].presence,
156
+ message_type: params[:message_type].presence || 'communication',
157
+ sender_user_id: params[:current_user_id].presence,
158
+ created_at: now,
159
+ updated_at: now
160
+ }
161
+ end
162
+
163
+ returning_cols = %w[id push_subscriber_id title body url icon
164
+ message_type sent_at received_at read_at
165
+ created_at updated_at sender_user_id]
166
+ result = PushMessage.insert_all(records, returning: returning_cols)
167
+
168
+ created = result.to_a
169
+ created.each { |r| PushDispatchJob.perform_later(r['id']) }
170
+
171
+ [{ enqueued: created.length }, 201]
172
+ end
173
+
174
+ def send_push_bulk(params) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
175
+ ids = Array(params[:push_subscriber_ids]).map(&:to_i).uniq
176
+ valid_ids = PushSubscriber.active.where(id: ids).pluck(:id)
177
+ failed = ids - valid_ids
178
+
179
+ return [{ created: [], failed: failed }, 201] if valid_ids.empty?
180
+
181
+ now = Time.current
182
+ records = valid_ids.map do |sub_id|
183
+ {
184
+ push_subscriber_id: sub_id,
185
+ title: params[:title],
186
+ body: params[:body],
187
+ url: params[:url].presence,
188
+ icon: params[:icon].presence,
189
+ message_type: params[:message_type].presence || 'communication',
190
+ sender_user_id: params[:sender_user_id].presence,
191
+ created_at: now,
192
+ updated_at: now
193
+ }
194
+ end
195
+
196
+ returning_cols = %w[id push_subscriber_id title body url icon
197
+ message_type sent_at received_at read_at
198
+ created_at updated_at sender_user_id]
199
+ result = PushMessage.insert_all(records, returning: returning_cols)
200
+
201
+ created = result.to_a
202
+ created.each { |r| PushDispatchJob.perform_later(r['id']) }
203
+
204
+ [{ created: created, failed: failed }, 201]
205
+ end
110
206
  end
@@ -1,3 +1,3 @@
1
1
  module ModelDrivenApi
2
- VERSION = "3.7.4".freeze
2
+ VERSION = "3.8.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: model_driven_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.7.4
4
+ version: 3.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriele Tassoni