Page MenuHomePhorge

D5667.1775273875.diff
No OneTemporary

Authored By
Unknown
Size
3 KB
Referenced Files
None
Subscribers
None

D5667.1775273875.diff

diff --git a/src/app/Http/Controllers/API/V4/DeviceController.php b/src/app/Http/Controllers/API/V4/DeviceController.php
--- a/src/app/Http/Controllers/API/V4/DeviceController.php
+++ b/src/app/Http/Controllers/API/V4/DeviceController.php
@@ -177,4 +177,37 @@
return $response;
}
+
+ /**
+ * Unclaim a device.
+ *
+ * @param string $token Device secret token
+ */
+ public function unclaim(string $token): JsonResponse
+ {
+ if (strlen($token) > 191) {
+ return $this->errorResponse(404);
+ }
+
+ $device = Device::where('hash', strtoupper($token))->first();
+
+ if (!$device) {
+ return $this->errorResponse(404);
+ }
+
+ $user = $this->guard()->user();
+
+ if (!$user->canDelete($device)) {
+ return $this->errorResponse(403);
+ }
+
+ $device->delete();
+
+ // TODO: Remove the role=device user account that owns the device?
+
+ return response()->json([
+ 'status' => 'success',
+ 'message' => self::trans('app.device-unclaim-success'),
+ ]);
+ }
}
diff --git a/src/resources/lang/en/app.php b/src/resources/lang/en/app.php
--- a/src/resources/lang/en/app.php
+++ b/src/resources/lang/en/app.php
@@ -28,6 +28,7 @@
'companion-delete-success' => 'Companion app has been removed.',
'device-claim-success' => 'The device has been claimed successfully.',
+ 'device-unclaim-success' => 'The device has been unclaimed successfully.',
'event-suspended' => 'Suspended',
'event-unsuspended' => 'Unsuspended',
diff --git a/src/routes/api.php b/src/routes/api.php
--- a/src/routes/api.php
+++ b/src/routes/api.php
@@ -198,6 +198,7 @@
Route::get('config/webmail', [API\V4\ConfigController::class, 'webmail']);
Route::post('device/{token}/claim', [API\V4\DeviceController::class, 'claim']);
+ Route::post('device/{token}/unclaim', [API\V4\DeviceController::class, 'unclaim']);
Route::get('device/{token}', [API\V4\DeviceController::class, 'info'])
->withoutMiddleware(['auth:api', 'scope:api']);
Route::get('device/{token}/plans', [API\V4\DeviceController::class, 'plans'])
diff --git a/src/tests/Feature/Controller/DeviceTest.php b/src/tests/Feature/Controller/DeviceTest.php
--- a/src/tests/Feature/Controller/DeviceTest.php
+++ b/src/tests/Feature/Controller/DeviceTest.php
@@ -290,6 +290,43 @@
$this->assertStringContainsString('2026-01-02', $entitlements[0]->updated_at->toDateString());
}
+ /**
+ * Test unclaiming a device (POST /api/v4/device/<hash>/unclaim)
+ */
+ public function testUnclaim(): void
+ {
+ $user = $this->getTestUser('jane@kolabnow.com');
+
+ // Unauthenticated
+ $response = $this->post('api/v4/device/unknown/unclaim');
+ $response->assertStatus(401);
+
+ // Unknown device hash
+ $response = $this->actingAs($user)->post('api/v4/device/unknown/unclaim', []);
+ $response->assertStatus(404);
+
+ [$device] = $this->initTestDevice();
+
+ $this->assertTrue($user->id != $device->account->id);
+ $this->assertCount(1, $device->entitlements);
+
+ // Unclaim an existing device owned by another user
+ $response = $this->actingAs($user)->post('api/v4/device/' . $this->hash . '/unclaim', []);
+ $response->assertStatus(403);
+
+ // Unclaim an existing device
+ $response = $this->actingAs($device->account)->post('api/v4/device/' . $this->hash . '/unclaim', []);
+ $response->assertStatus(200);
+
+ $json = $response->json();
+
+ $device->refresh();
+ $this->assertSame('success', $json['status']);
+ $this->assertSame('The device has been unclaimed successfully.', $json['message']);
+ $this->assertTrue($device->trashed());
+ $this->assertCount(0, $device->entitlements);
+ }
+
private function initTestDevice(): array
{
$sku = Sku::withEnvTenantContext()->where('title', 'device')->first();

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 3:37 AM (3 h, 43 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18827930
Default Alt Text
D5667.1775273875.diff (3 KB)

Event Timeline