Add service API to list mailbox files for Ladill Mail.
Deploy Ladill Transfer / deploy (push) Successful in 1m8s
Deploy Ladill Transfer / deploy (push) Successful in 1m8s
Expose GET /api/v1/transfers/files so webmail can sync the mobile Files tab with Transfer storage. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Transfer;
|
||||
use App\Models\TransferFile;
|
||||
use App\Services\Identity\MailboxUserResolver;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use RuntimeException;
|
||||
|
||||
/** Service-to-service file listing for Ladill Mail (synced with Transfer Files). */
|
||||
class TransferFilesController extends Controller
|
||||
{
|
||||
public function __construct(private MailboxUserResolver $users) {}
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
if ($request->attributes->get('service_caller') !== 'webmail') {
|
||||
return response()->json(['message' => 'Forbidden.'], 403);
|
||||
}
|
||||
|
||||
$data = $request->validate([
|
||||
'mailbox' => ['required', 'email', 'max:255'],
|
||||
'q' => ['nullable', 'string', 'max:120'],
|
||||
'page' => ['nullable', 'integer', 'min:1'],
|
||||
'sort' => ['nullable', 'in:newest,oldest,name,size'],
|
||||
]);
|
||||
|
||||
try {
|
||||
$user = $this->users->resolve((string) $data['mailbox']);
|
||||
} catch (RuntimeException $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 422);
|
||||
}
|
||||
|
||||
$search = trim((string) ($data['q'] ?? ''));
|
||||
$sort = (string) ($data['sort'] ?? 'newest');
|
||||
|
||||
$filesQuery = TransferFile::query()
|
||||
->whereHas('transfer', fn ($q) => $q
|
||||
->where('user_id', $user->id)
|
||||
->where('status', '!=', Transfer::STATUS_DELETED)
|
||||
->where(function ($query) {
|
||||
$query->where('is_root_storage', true)
|
||||
->orWhere(function ($nested) {
|
||||
$nested->where('is_folder', false)->where('is_root_storage', false);
|
||||
});
|
||||
}))
|
||||
->when($search !== '', fn ($q) => $q->where('original_name', 'like', '%'.$search.'%'))
|
||||
->with(['transfer.qrCode'])
|
||||
->when($sort === 'oldest', fn ($q) => $q->oldest())
|
||||
->when($sort === 'name', fn ($q) => $q->orderBy('original_name'))
|
||||
->when($sort === 'size', fn ($q) => $q->orderByDesc('size_bytes'))
|
||||
->when($sort === 'newest', fn ($q) => $q->latest());
|
||||
|
||||
$paginator = $filesQuery->paginate(30, ['*'], 'page', (int) ($data['page'] ?? 1));
|
||||
|
||||
$items = collect($paginator->items())->map(function (TransferFile $file) {
|
||||
$transfer = $file->transfer;
|
||||
$title = (string) ($transfer?->title ?? '');
|
||||
|
||||
return [
|
||||
'id' => $file->id,
|
||||
'name' => $file->original_name,
|
||||
'size_bytes' => (int) $file->size_bytes,
|
||||
'mime_type' => $file->mime_type,
|
||||
'source' => $this->sourceFor($transfer),
|
||||
'public_url' => $transfer?->qrCode?->publicUrl(),
|
||||
'transfer_id' => $transfer?->id,
|
||||
'transfer_title' => $title !== '' ? $title : null,
|
||||
'created_at' => $file->created_at?->toIso8601String(),
|
||||
];
|
||||
})->values();
|
||||
|
||||
return response()->json([
|
||||
'data' => $items,
|
||||
'meta' => [
|
||||
'current_page' => $paginator->currentPage(),
|
||||
'last_page' => $paginator->lastPage(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'total' => $paginator->total(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
private function sourceFor(?Transfer $transfer): string
|
||||
{
|
||||
if ($transfer === null) {
|
||||
return 'transfer';
|
||||
}
|
||||
|
||||
if ($transfer->is_root_storage) {
|
||||
return 'transfer';
|
||||
}
|
||||
|
||||
$title = strtolower(trim($transfer->title));
|
||||
if (str_starts_with($title, 'email:') || str_starts_with($title, 'email attachment:')) {
|
||||
return 'mail';
|
||||
}
|
||||
|
||||
return 'transfer';
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware('auth.service:transfer')->prefix('v1')->group(function () {
|
||||
Route::post('/transfers', [TransferController::class, 'store']);
|
||||
Route::get('/transfers/files', [\App\Http\Controllers\Api\TransferFilesController::class, 'index']);
|
||||
Route::post('/transfers/upload/init', [ChunkedUploadController::class, 'init']);
|
||||
Route::post('/transfers/upload/chunk', [ChunkedUploadController::class, 'chunk']);
|
||||
Route::post('/transfers/upload/finalize', [ChunkedUploadController::class, 'finalize']);
|
||||
|
||||
Reference in New Issue
Block a user