diff --git a/packages/Webkul/Admin/src/Http/Controllers/Mail/EmailController.php b/packages/Webkul/Admin/src/Http/Controllers/Mail/EmailController.php index 3cd8aab1dc..49ab75359c 100644 --- a/packages/Webkul/Admin/src/Http/Controllers/Mail/EmailController.php +++ b/packages/Webkul/Admin/src/Http/Controllers/Mail/EmailController.php @@ -3,22 +3,23 @@ namespace Webkul\Admin\Http\Controllers\Mail; use Exception; +use Illuminate\View\View; use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Mail; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Event; -use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Storage; -use Illuminate\View\View; -use Webkul\Admin\DataGrids\Mail\EmailDataGrid; +use Webkul\Email\Mails\Email; +use Webkul\Email\Enums\SupportedFolderEnum; +use Webkul\Lead\Repositories\LeadRepository; use Webkul\Admin\Http\Controllers\Controller; -use Webkul\Admin\Http\Requests\MassDestroyRequest; -use Webkul\Admin\Http\Requests\MassUpdateRequest; +use Webkul\Admin\DataGrids\Mail\EmailDataGrid; use Webkul\Admin\Http\Resources\EmailResource; -use Webkul\Email\InboundEmailProcessor\Contracts\InboundEmailProcessor; -use Webkul\Email\Mails\Email; -use Webkul\Email\Repositories\AttachmentRepository; use Webkul\Email\Repositories\EmailRepository; -use Webkul\Lead\Repositories\LeadRepository; +use Webkul\Admin\Http\Requests\MassUpdateRequest; +use Webkul\Admin\Http\Requests\MassDestroyRequest; +use Webkul\Email\Repositories\AttachmentRepository; +use Webkul\Email\InboundEmailProcessor\Contracts\InboundEmailProcessor; class EmailController extends Controller { @@ -38,25 +39,21 @@ public function __construct( */ public function index(): View|JsonResponse|RedirectResponse { - if (! request('route')) { - return redirect()->route('admin.mail.index', ['route' => 'inbox']); - } + $route = request('route'); - if (! bouncer()->hasPermission('mail.'.request('route'))) { - abort(401, 'This action is unauthorized'); + if (! $route) { + return redirect()->route('admin.mail.index', ['route' => SupportedFolderEnum::INBOX->value]); } - switch (request('route')) { - case 'compose': - return view('admin::mail.compose'); - - default: - if (request()->ajax()) { - return datagrid(EmailDataGrid::class)->process(); - } + if (! bouncer()->hasPermission('mail.' . $route)) { + abort(401, trans('admin::app.mail.unauthorized')); + } - return view('admin::mail.index'); + if (request()->ajax()) { + return datagrid(EmailDataGrid::class)->process(); } + + return view('admin::mail.index', compact('route')); } /** @@ -66,8 +63,20 @@ public function index(): View|JsonResponse|RedirectResponse */ public function view() { + $route = request('route'); + $email = $this->emailRepository - ->with(['emails', 'attachments', 'emails.attachments', 'lead', 'lead.person', 'lead.tags', 'lead.source', 'lead.type', 'person']) + ->with([ + 'emails', + 'attachments', + 'emails.attachments', + 'lead', + 'lead.person', + 'lead.tags', + 'lead.source', + 'lead.type', + 'person' + ]) ->findOrFail(request('id')); if ($userIds = bouncer()->getAuthorizedUserIds()) { @@ -85,13 +94,13 @@ public function view() unset($email->lead_id); } - if (request('route') == 'draft') { + if ($route == SupportedFolderEnum::DRAFT->value) { return response()->json([ 'data' => new EmailResource($email), ]); } - return view('admin::mail.view', compact('email')); + return view('admin::mail.view', compact('email', 'route')); } /** @@ -116,7 +125,7 @@ public function store() Mail::send(new Email($email)); $this->emailRepository->update([ - 'folders' => ['sent'], + 'folders' => [SupportedFolderEnum::SENT->value], ], $email->id); } catch (\Exception $e) { } @@ -134,12 +143,12 @@ public function store() if (request('is_draft')) { session()->flash('success', trans('admin::app.mail.saved-to-draft')); - return redirect()->route('admin.mail.index', ['route' => 'draft']); + return redirect()->route('admin.mail.index', ['route' => SupportedFolderEnum::DRAFT->value]); } session()->flash('success', trans('admin::app.mail.create-success')); - return redirect()->route('admin.mail.index', ['route' => 'sent']); + return redirect()->route('admin.mail.index', ['route' => SupportedFolderEnum::SENT->value]); } /** @@ -155,7 +164,7 @@ public function update($id) $data = request()->all(); if (! is_null(request('is_draft'))) { - $data['folders'] = request('is_draft') ? ['draft'] : ['outbox']; + $data['folders'] = request('is_draft') ? [SupportedFolderEnum::DRAFT->value] : [SupportedFolderEnum::OUTBOX->value]; } $email = $this->emailRepository->update($data, request('id') ?? $id); @@ -167,7 +176,7 @@ public function update($id) Mail::send(new Email($email)); $this->emailRepository->update([ - 'folders' => ['inbox', 'sent'], + 'folders' => [SupportedFolderEnum::INBOX->value, SupportedFolderEnum::SENT->value], ], $email->id); } catch (\Exception $e) { } @@ -177,11 +186,11 @@ public function update($id) if (request('is_draft')) { session()->flash('success', trans('admin::app.mail.saved-to-draft')); - return redirect()->route('admin.mail.index', ['route' => 'draft']); + return redirect()->route('admin.mail.index', ['route' => SupportedFolderEnum::DRAFT->value]); } else { session()->flash('success', trans('admin::app.mail.create-success')); - return redirect()->route('admin.mail.index', ['route' => 'inbox']); + return redirect()->route('admin.mail.index', ['route' => SupportedFolderEnum::INBOX->value]); } } @@ -268,9 +277,9 @@ public function destroy(int $id): JsonResponse|RedirectResponse $parentId = $email->parent_id; - if (request('type') == 'trash') { + if (request('type') == SupportedFolderEnum::TRASH->value) { $this->emailRepository->update([ - 'folders' => ['trash'], + 'folders' => [SupportedFolderEnum::TRASH->value], ], $id); } else { $this->emailRepository->delete($id); @@ -290,7 +299,7 @@ public function destroy(int $id): JsonResponse|RedirectResponse return redirect()->back(); } - return redirect()->route('admin.mail.index', ['route' => 'inbox']); + return redirect()->route('admin.mail.index', ['route' => SupportedFolderEnum::INBOX->value]); } catch (\Exception $exception) { if (request()->ajax()) { return response()->json([ @@ -315,8 +324,8 @@ public function massDestroy(MassDestroyRequest $massDestroyRequest): JsonRespons foreach ($mails as $email) { Event::dispatch('email.'.$massDestroyRequest->input('type').'.before', $email->id); - if ($massDestroyRequest->input('type') == 'trash') { - $this->emailRepository->update(['folders' => ['trash']], $email->id); + if ($massDestroyRequest->input('type') == SupportedFolderEnum::TRASH->value) { + $this->emailRepository->update(['folders' => [SupportedFolderEnum::TRASH->value]], $email->id); } else { $this->emailRepository->delete($email->id); } diff --git a/packages/Webkul/Admin/src/Http/Middleware/SanitizeUrl.php b/packages/Webkul/Admin/src/Http/Middleware/SanitizeUrl.php new file mode 100644 index 0000000000..14deb512ff --- /dev/null +++ b/packages/Webkul/Admin/src/Http/Middleware/SanitizeUrl.php @@ -0,0 +1,45 @@ +route('route'); + + $sanitizedRoute = Str::of($route)->ascii()->lower()->replaceMatches('/[^a-z0-9_-]/', '')->__toString(); + + $request->route()->setParameter('route', $sanitizedRoute); + + /** + * Whitelist acceptable route values to prevent unexpected input + */ + $allowedRoutes = [ + SupportedFolderEnum::INBOX->value, + SupportedFolderEnum::IMPORTANT->value, + SupportedFolderEnum::STARRED->value, + SupportedFolderEnum::DRAFT->value, + SupportedFolderEnum::OUTBOX->value, + SupportedFolderEnum::SENT->value, + SupportedFolderEnum::SPAM->value, + SupportedFolderEnum::TRASH->value, + ]; + + if (! in_array($route, $allowedRoutes, true)) { + abort(401, trans('admin::app.mail.invalid-route')); + } + + return $next($request); + } +} diff --git a/packages/Webkul/Admin/src/Providers/AdminServiceProvider.php b/packages/Webkul/Admin/src/Providers/AdminServiceProvider.php index d8be1f1ca8..32efe11af6 100644 --- a/packages/Webkul/Admin/src/Providers/AdminServiceProvider.php +++ b/packages/Webkul/Admin/src/Providers/AdminServiceProvider.php @@ -2,16 +2,17 @@ namespace Webkul\Admin\Providers; -use Illuminate\Contracts\Debug\ExceptionHandler; -use Illuminate\Database\Eloquent\Relations\Relation; -use Illuminate\Foundation\AliasLoader; use Illuminate\Routing\Router; use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Route; +use Illuminate\Contracts\Debug\ExceptionHandler; +use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Foundation\AliasLoader; use Illuminate\Support\ServiceProvider; use Webkul\Admin\Exceptions\Handler; -use Webkul\Admin\Http\Middleware\Bouncer as BouncerMiddleware; +use Webkul\Admin\Http\Middleware\SanitizeUrl; use Webkul\Admin\Http\Middleware\Locale; +use Webkul\Admin\Http\Middleware\Bouncer as BouncerMiddleware; class AdminServiceProvider extends ServiceProvider { @@ -24,6 +25,8 @@ public function boot(Router $router): void $router->aliasMiddleware('admin_locale', Locale::class); + $router->aliasMiddleware('sanitize_url', SanitizeUrl::class); + include __DIR__.'/../Http/helpers.php'; Route::middleware(['web', 'admin_locale', 'user']) diff --git a/packages/Webkul/Admin/src/Resources/lang/ar/app.php b/packages/Webkul/Admin/src/Resources/lang/ar/app.php index 336cdb2ab7..bce8471ba3 100644 --- a/packages/Webkul/Admin/src/Resources/lang/ar/app.php +++ b/packages/Webkul/Admin/src/Resources/lang/ar/app.php @@ -1673,11 +1673,15 @@ 'delete' => 'حذف', ], ], + 'create-success' => 'تم إرسال البريد الإلكتروني بنجاح.', 'update-success' => 'تم تحديث البريد الإلكتروني بنجاح.', 'mass-update-success' => 'تم تحديث البريد الإلكتروني بنجاح.', 'delete-success' => 'تم حذف البريد الإلكتروني بنجاح.', 'delete-failed' => 'لا يمكن حذف البريد الإلكتروني.', + 'invalid-route' => 'مسار غير صالح للبريد.', + 'unauthorized' => 'هذا الإجراء غير مصرح به.', + 'view' => [ 'title' => 'الرسائل', 'subject' => ':الموضوع', diff --git a/packages/Webkul/Admin/src/Resources/lang/en/app.php b/packages/Webkul/Admin/src/Resources/lang/en/app.php index d6f3382215..19bc6686ec 100644 --- a/packages/Webkul/Admin/src/Resources/lang/en/app.php +++ b/packages/Webkul/Admin/src/Resources/lang/en/app.php @@ -1831,6 +1831,8 @@ 'mass-update-success' => 'Emails updated successfully.', 'delete-success' => 'Email deleted successfully.', 'delete-failed' => 'Email can not be deleted.', + 'invalid-route' => 'Invalid route for mail.', + 'unauthorized' => 'This action is unauthorized.', 'view' => [ 'title' => 'Mails', diff --git a/packages/Webkul/Admin/src/Resources/lang/es/app.php b/packages/Webkul/Admin/src/Resources/lang/es/app.php index 45e3e7bb1f..e2e906a64a 100644 --- a/packages/Webkul/Admin/src/Resources/lang/es/app.php +++ b/packages/Webkul/Admin/src/Resources/lang/es/app.php @@ -1673,11 +1673,15 @@ 'delete' => 'Eliminar', ], ], + 'create-success' => 'Correo enviado con éxito.', 'update-success' => 'Correo actualizado con éxito.', 'mass-update-success' => 'Correos actualizados con éxito.', 'delete-success' => 'Correo eliminado con éxito.', 'delete-failed' => 'No se puede eliminar el correo.', + 'invalid-route' => 'Ruta inválida para el correo.', + 'unauthorized' => 'Esta acción no está autorizada.', + 'view' => [ 'title' => 'Correos', 'subject' => ':subject', diff --git a/packages/Webkul/Admin/src/Resources/lang/fa/app.php b/packages/Webkul/Admin/src/Resources/lang/fa/app.php index 1e8e24487c..c615396927 100644 --- a/packages/Webkul/Admin/src/Resources/lang/fa/app.php +++ b/packages/Webkul/Admin/src/Resources/lang/fa/app.php @@ -1678,6 +1678,8 @@ 'mass-update-success' => 'ایمیل‌ها با موفقیت به‌روزرسانی شدند.', 'delete-success' => 'ایمیل با موفقیت حذف شد.', 'delete-failed' => 'ایمیل قابل حذف نیست.', + 'invalid-route' => 'مسیر نامعتبر برای ایمیل.', + 'unauthorized' => 'این عمل مجاز نیست.', 'view' => [ 'title' => 'ایمیل‌ها', 'subject' => ':subject', diff --git a/packages/Webkul/Admin/src/Resources/lang/pt_BR/app.php b/packages/Webkul/Admin/src/Resources/lang/pt_BR/app.php index a7bf31c309..36a45b5f25 100644 --- a/packages/Webkul/Admin/src/Resources/lang/pt_BR/app.php +++ b/packages/Webkul/Admin/src/Resources/lang/pt_BR/app.php @@ -1673,11 +1673,15 @@ 'delete' => 'Excluir', ], ], + 'create-success' => 'E-mail enviado com sucesso.', 'update-success' => 'E-mail atualizado com sucesso.', 'mass-update-success' => 'E-mails atualizados com sucesso.', 'delete-success' => 'E-mail excluído com sucesso.', 'delete-failed' => 'E-mail não pode ser excluído.', + 'invalid-route' => 'Rota inválida para o e-mail.', + 'unauthorized' => 'Esta ação não está autorizada.', + 'view' => [ 'title' => 'E-mails', 'subject' => ':subject', diff --git a/packages/Webkul/Admin/src/Resources/lang/tr/app.php b/packages/Webkul/Admin/src/Resources/lang/tr/app.php index 08de929f61..cc70d7ec72 100644 --- a/packages/Webkul/Admin/src/Resources/lang/tr/app.php +++ b/packages/Webkul/Admin/src/Resources/lang/tr/app.php @@ -1673,11 +1673,15 @@ 'delete' => 'Sil', ], ], + 'create-success' => 'E-posta başarıyla gönderildi.', 'update-success' => 'E-posta başarıyla güncellendi.', 'mass-update-success' => 'E-postalar başarıyla güncellendi.', 'delete-success' => 'E-posta başarıyla silindi.', 'delete-failed' => 'E-posta silinemedi.', + 'invalid-route' => 'Geçersiz rota için mail.', + 'unauthorized' => 'Bu işlem yetkilendirilmemiştir.', + 'view' => [ 'title' => 'Mails', 'subject' => ':subject', diff --git a/packages/Webkul/Admin/src/Resources/lang/vi/app.php b/packages/Webkul/Admin/src/Resources/lang/vi/app.php index 7766bc9086..a7291e1151 100644 --- a/packages/Webkul/Admin/src/Resources/lang/vi/app.php +++ b/packages/Webkul/Admin/src/Resources/lang/vi/app.php @@ -1673,11 +1673,15 @@ 'delete' => 'Xóa', ], ], + 'create-success' => 'Email đã được gửi thành công.', 'update-success' => 'Email đã được cập nhật thành công.', 'mass-update-success' => 'Các email đã được cập nhật thành công.', 'delete-success' => 'Email đã được xóa thành công.', 'delete-failed' => 'Email không thể bị xóa.', + 'invalid-route' => 'Đường dẫn không hợp lệ cho email.', + 'unauthorized' => 'Hành động này không được phép.', + 'view' => [ 'title' => 'Thư', 'subject' => ':subject', diff --git a/packages/Webkul/Admin/src/Resources/views/mail/index.blade.php b/packages/Webkul/Admin/src/Resources/views/mail/index.blade.php index fd59cb26b7..a7400abaa6 100644 --- a/packages/Webkul/Admin/src/Resources/views/mail/index.blade.php +++ b/packages/Webkul/Admin/src/Resources/views/mail/index.blade.php @@ -1,24 +1,24 @@ - @lang('admin::app.mail.index.' . request('route')) + @lang('admin::app.mail.index.' . $route)
{!! view_render_event('admin.mail.create.breadcrumbs.before') !!} - + {!! view_render_event('admin.mail.create.breadcrumbs.after') !!}
- @lang('admin::app.mail.index.' . request('route')) + @lang('admin::app.mail.index.' . $route)
@@ -54,12 +54,12 @@ class="primary-button" type="text/x-template" id="v-mail-template" > - {!! view_render_event('admin.mail.'.request('route').'.datagrid.before') !!} + {!! view_render_event('admin.mail.'. $route .'.datagrid.before') !!}