Skip to content

Commit f8f3054

Browse files
authored
Merge pull request #7930 from ProcessMaker/feature/FOUR-20548
feature/FOUR-20548 Create new tables and endpoints to register the instances that had installed the bundles for notifications
2 parents dec98c0 + a82b621 commit f8f3054

File tree

12 files changed

+230
-4
lines changed

12 files changed

+230
-4
lines changed

ProcessMaker/Http/Controllers/Api/DevLinkController.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@
22

33
namespace ProcessMaker\Http\Controllers\Api;
44

5+
use Illuminate\Database\Eloquent\ModelNotFoundException;
56
use Illuminate\Http\Request;
7+
use Illuminate\Support\Facades\Notification;
68
use Illuminate\Validation\Rule;
79
use ProcessMaker\Exception\ValidationException;
810
use ProcessMaker\Http\Controllers\Controller;
911
use ProcessMaker\Http\Resources\ApiCollection;
1012
use ProcessMaker\Jobs\DevLinkInstall;
1113
use ProcessMaker\Models\Bundle;
1214
use ProcessMaker\Models\BundleAsset;
15+
use ProcessMaker\Models\BundleInstance;
1316
use ProcessMaker\Models\BundleSetting;
1417
use ProcessMaker\Models\DevLink;
1518
use ProcessMaker\Models\Setting;
19+
use ProcessMaker\Models\User;
20+
use ProcessMaker\Notifications\BundleUpdatedNotification;
1621

1722
class DevLinkController extends Controller
1823
{
@@ -154,12 +159,34 @@ public function updateBundle(Request $request, Bundle $bundle)
154159

155160
public function increaseBundleVersion(Bundle $bundle)
156161
{
162+
$bundle->notifyBundleUpdated();
163+
157164
$bundle->version = $bundle->version + 1;
158165
$bundle->saveOrFail();
159166

160167
return $bundle;
161168
}
162169

170+
public function bundleUpdated($bundleId, $token)
171+
{
172+
try {
173+
$bundle = Bundle::where('remote_id', $bundleId)->firstOrFail();
174+
} catch (ModelNotFoundException $e) {
175+
return response()->json(['error' => 'Bundle not found'], 403);
176+
}
177+
178+
$storedToken = $bundle->webhook_token;
179+
180+
if ($token !== $storedToken) {
181+
return response()->json(['error' => 'Invalid token'], 403);
182+
}
183+
$adminUsers = User::where('is_administrator', true)->get();
184+
185+
Notification::send($adminUsers, new BundleUpdatedNotification($bundle));
186+
187+
return $bundle;
188+
}
189+
163190
public function deleteBundle(Bundle $bundle)
164191
{
165192
$bundle->delete();
@@ -198,6 +225,14 @@ public function reinstallBundle(Request $request, Bundle $bundle)
198225
];
199226
}
200227

228+
public function addBundleInstance(Request $request, Bundle $bundle)
229+
{
230+
BundleInstance::create([
231+
'bundle_id' => $bundle->id,
232+
'instance_url' => $request->input('instance_url'),
233+
]);
234+
}
235+
201236
public function exportLocalBundle(Bundle $bundle)
202237
{
203238
return ['payloads' => $bundle->export()];

ProcessMaker/Jobs/DevLinkInstall.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public function __construct(
4848
*/
4949
public function handle(): void
5050
{
51+
//log
52+
\Log::info('DevLinkInstall job started: ' . $this->devLinkId);
5153
$devLink = DevLink::findOrFail($this->devLinkId);
5254
$logger = new Logger($this->userId);
5355

ProcessMaker/Models/Bundle.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace ProcessMaker\Models;
44

55
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use Illuminate\Support\Facades\Http;
67
use ProcessMaker\Exception\ExporterNotSupported;
78
use ProcessMaker\Exception\ValidationException;
89
use ProcessMaker\ImportExport\Importer;
@@ -400,4 +401,22 @@ public function reinstall(string $mode, Logger $logger = null)
400401

401402
$logger?->setStatus('done');
402403
}
404+
405+
public function notifyBundleUpdated()
406+
{
407+
$bundleInstances = BundleInstance::where('bundle_id', $this->id)->get();
408+
foreach ($bundleInstances as $bundleInstance) {
409+
$url = $bundleInstance->instance_url;
410+
411+
try {
412+
$response = Http::post($url);
413+
414+
if ($response->status() === 403) {
415+
\Log::error("Failed to notify bundle update for URL: $url " . $response);
416+
}
417+
} catch (\Exception $e) {
418+
\Log::error('Error notifying bundle update: ' . $e->getMessage());
419+
}
420+
}
421+
}
403422
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace ProcessMaker\Models;
4+
5+
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use ProcessMaker\Models\ProcessMakerModel;
7+
8+
class BundleInstance extends ProcessMakerModel
9+
{
10+
use HasFactory;
11+
12+
protected $fillable = [
13+
'bundle_id',
14+
'instance_url',
15+
];
16+
17+
public function bundle()
18+
{
19+
return $this->belongsTo(Bundle::class);
20+
}
21+
}

ProcessMaker/Models/DevLink.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ public function installRemoteBundle($remoteBundleId, $updateType)
138138
$this->logger->status(__('Downloading bundle from remote instance'));
139139

140140
$bundleInfo = $this->remoteBundle($remoteBundleId)->json();
141+
$token = Str::random(60);
142+
143+
$addBundleInstance = $this->client()->post(
144+
route('api.devlink.add-bundle-instance', ['bundle' => $remoteBundleId], false),
145+
[
146+
'instance_url' => env('APP_URL') . '/devlink/bundle-updated/' . $remoteBundleId . '/' . $token,
147+
]
148+
);
141149

142150
$bundleExport = $this->client()->get(
143151
route('api.devlink.export-local-bundle', ['bundle' => $remoteBundleId], false)
@@ -160,6 +168,7 @@ public function installRemoteBundle($remoteBundleId, $updateType)
160168
'name' => $bundleInfo['name'],
161169
'published' => $bundleInfo['published'],
162170
'version' => $bundleInfo['version'],
171+
'webhook_token' => $token,
163172
]
164173
);
165174

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
namespace ProcessMaker\Notifications;
4+
5+
use Illuminate\Bus\Queueable;
6+
use Illuminate\Contracts\Queue\ShouldQueue;
7+
use Illuminate\Notifications\Messages\BroadcastMessage;
8+
use Illuminate\Notifications\Messages\MailMessage;
9+
use Illuminate\Notifications\Notification;
10+
use ProcessMaker\Models\Bundle;
11+
12+
class BundleUpdatedNotification extends Notification
13+
{
14+
use Queueable;
15+
16+
private $bundleName;
17+
18+
private $bundleUid;
19+
20+
/**
21+
* Create a new notification instance.
22+
*/
23+
public function __construct(Bundle $bundle)
24+
{
25+
$this->bundleName = $bundle->name;
26+
$this->bundleUid = $bundle->id;
27+
}
28+
29+
/**
30+
* Get the notification's delivery channels.
31+
*
32+
* @return array<int, string>
33+
*/
34+
public function via(object $notifiable): array
35+
{
36+
return ['broadcast', NotificationChannel::class];
37+
}
38+
39+
/**
40+
* Get the mail representation of the notification.
41+
*/
42+
public function toMail(object $notifiable): MailMessage
43+
{
44+
return (new MailMessage)
45+
->line('The introduction to the notification.')
46+
->action('Notification Action', url('/'))
47+
->line('Thank you for using our application!');
48+
}
49+
50+
/**
51+
* Get the array representation of the notification.
52+
*
53+
* @return array<string, mixed>
54+
*/
55+
public function toArray($notifiable)
56+
{
57+
$bundle = Bundle::find($this->bundleUid);
58+
59+
return [
60+
'type' => 'BUNDLE_UPDATED',
61+
'message' => sprintf('Bundle updated: %s', $this->bundleName),
62+
'dateTime' => $bundle->updated_at->toIso8601String(),
63+
'name' => $this->bundleName,
64+
'bundleName' => $this->bundleName,
65+
'url' => sprintf(
66+
'/admin/devlink/local-bundles/%s/',
67+
$this->bundleUid
68+
),
69+
];
70+
}
71+
72+
public function toDatabase($notifiable)
73+
{
74+
return $this->toArray($notifiable);
75+
}
76+
77+
public function toBroadcast($notifiable)
78+
{
79+
return new BroadcastMessage($this->toArray($notifiable));
80+
}
81+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
/**
9+
* Run the migrations.
10+
*/
11+
public function up(): void
12+
{
13+
Schema::create('bundle_instances', function (Blueprint $table) {
14+
$table->id();
15+
$table->unsignedBigInteger('bundle_id');
16+
$table->string('instance_url');
17+
$table->timestamps();
18+
19+
$table->index(['bundle_id']);
20+
});
21+
}
22+
23+
/**
24+
* Reverse the migrations.
25+
*/
26+
public function down(): void
27+
{
28+
Schema::dropIfExists('bundle_instances');
29+
}
30+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
/**
9+
* Run the migrations.
10+
*/
11+
public function up(): void
12+
{
13+
Schema::table('bundles', function (Blueprint $table) {
14+
$table->string('webhook_token')->nullable();
15+
});
16+
}
17+
18+
/**
19+
* Reverse the migrations.
20+
*/
21+
public function down(): void
22+
{
23+
Schema::table('bundles', function (Blueprint $table) {
24+
$table->dropColumn('webhook_token');
25+
});
26+
}
27+
};

resources/js/admin/devlink/components/platformConfigurations.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,4 @@ export default [
3131
type: "public_files",
3232
name: "Public Files",
3333
},
34-
{
35-
type: "translations",
36-
name: "Translations",
37-
},
3834
];

resources/js/notifications/components/notification-message.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const messages = {
3636
TASK_OVERDUE: "Task {{- subject }} is overdue. Originally due on {{- due }}",
3737
PROCESS_CREATED: "{{- user}} started the process {{- subject }}",
3838
PROCESS_COMPLETED: "{{- subject }} completed",
39+
BUNDLE_UPDATED: "The bundle {{- subject }} has a new version. Click to check it",
3940
ERROR_EXECUTION: "{{- subject }} caused an error",
4041
COMMENT: "{{- user}} commented on {{- subject}}",
4142
"ProcessMaker\\Notifications\\ImportReady": "Imported {{- subject }}",

0 commit comments

Comments
 (0)