mailwolt/app/Http/Controllers/Api/V1/MailboxController.php

133 lines
4.8 KiB
PHP

<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use App\Models\Domain;
use App\Models\MailUser;
use App\Services\WebhookService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class MailboxController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = MailUser::with('domain')
->where('is_system', false);
if ($request->filled('domain')) {
$query->whereHas('domain', fn($q) => $q->where('domain', $request->domain));
}
if ($request->filled('active')) {
$query->where('is_active', filter_var($request->active, FILTER_VALIDATE_BOOLEAN));
}
$mailboxes = $query->orderBy('email')->paginate(100);
return response()->json([
'data' => $mailboxes->map(fn($m) => $this->format($m)),
'meta' => ['total' => $mailboxes->total(), 'per_page' => $mailboxes->perPage(), 'current_page' => $mailboxes->currentPage()],
]);
}
public function show(int $id): JsonResponse
{
$mailbox = MailUser::with('domain')->where('is_system', false)->findOrFail($id);
return response()->json(['data' => $this->format($mailbox)]);
}
public function store(Request $request): JsonResponse
{
$request->tokenCan('mailboxes:write') || abort(403, 'Scope mailboxes:write required.');
if ($request->isSandbox ?? false) {
return response()->json(['data' => array_merge(['id' => 9999], $request->only('email')), 'sandbox' => true], 201);
}
$data = $request->validate([
'email' => 'required|email|unique:mail_users,email',
'password' => 'required|string|min:8',
'display_name'=> 'nullable|string|max:120',
'quota_mb' => 'nullable|integer|min:0',
'is_active' => 'nullable|boolean',
]);
[$local, $domainName] = explode('@', $data['email']);
$domain = Domain::where('domain', $domainName)->firstOrFail();
$mailbox = MailUser::create([
'domain_id' => $domain->id,
'localpart' => $local,
'email' => $data['email'],
'display_name' => $data['display_name'] ?? null,
'password_hash'=> '{ARGON2I}' . base64_encode(password_hash($data['password'], PASSWORD_ARGON2I)),
'quota_mb' => $data['quota_mb'] ?? $domain->default_quota_mb ?? 1024,
'is_active' => $data['is_active'] ?? true,
]);
if (!($request->isSandbox ?? false)) {
app(WebhookService::class)->dispatch('mailbox.created', $this->format($mailbox->load('domain')));
}
return response()->json(['data' => $this->format($mailbox->load('domain'))], 201);
}
public function update(Request $request, int $id): JsonResponse
{
$request->tokenCan('mailboxes:write') || abort(403, 'Scope mailboxes:write required.');
$mailbox = MailUser::where('is_system', false)->findOrFail($id);
if ($request->isSandbox ?? false) {
return response()->json(['data' => $this->format($mailbox), 'sandbox' => true]);
}
$data = $request->validate([
'display_name' => 'nullable|string|max:120',
'quota_mb' => 'nullable|integer|min:0',
'is_active' => 'nullable|boolean',
'can_login' => 'nullable|boolean',
]);
$mailbox->update(array_filter($data, fn($v) => !is_null($v)));
if (!($request->isSandbox ?? false)) {
app(WebhookService::class)->dispatch('mailbox.updated', $this->format($mailbox->load('domain')));
}
return response()->json(['data' => $this->format($mailbox->load('domain'))]);
}
public function destroy(Request $request, int $id): JsonResponse
{
$request->tokenCan('mailboxes:write') || abort(403, 'Scope mailboxes:write required.');
$mailbox = MailUser::where('is_system', false)->findOrFail($id);
if ($request->isSandbox ?? false) {
return response()->json(['sandbox' => true], 204);
}
$formatted = $this->format($mailbox->load('domain'));
$mailbox->delete();
app(WebhookService::class)->dispatch('mailbox.deleted', $formatted);
return response()->json(null, 204);
}
private function format(MailUser $m): array
{
return [
'id' => $m->id,
'email' => $m->email,
'display_name' => $m->display_name,
'domain' => $m->domain?->domain,
'quota_mb' => $m->quota_mb,
'is_active' => $m->is_active,
'can_login' => $m->can_login,
'last_login_at'=> $m->last_login_at?->toIso8601String(),
'created_at' => $m->created_at->toIso8601String(),
];
}
}