Skip to content

Commit 662323d

Browse files
authored
Merge pull request #10 from riodwanto/feature/verification
Feature/Verification
2 parents 07a440a + bea7db2 commit 662323d

File tree

23 files changed

+676
-520
lines changed

23 files changed

+676
-520
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
namespace App\Filament\Pages\Auth;
4+
5+
use App\Settings\MailSettings;
6+
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
7+
use Exception;
8+
use Filament\Actions\Action;
9+
use Filament\Facades\Filament;
10+
use Filament\Notifications\Auth\VerifyEmail;
11+
use Filament\Notifications\Notification;
12+
use Illuminate\Contracts\Support\Htmlable;
13+
use Filament\Pages\Auth\EmailVerification\EmailVerificationPrompt;
14+
15+
class EmailVerification extends EmailVerificationPrompt
16+
{
17+
18+
/**
19+
* @var view-string
20+
*/
21+
protected static string $view = 'filament-panels::pages.auth.email-verification.email-verification-prompt';
22+
23+
public function resendNotificationAction(): Action
24+
{
25+
return Action::make('resendNotification')
26+
->link()
27+
->label(__('filament-panels::pages/auth/email-verification/email-verification-prompt.actions.resend_notification.label') . '.')
28+
->action(function (MailSettings $settings = null): void {
29+
try {
30+
$this->rateLimit(2);
31+
} catch (TooManyRequestsException $exception) {
32+
Notification::make()
33+
->title(__('filament-panels::pages/auth/email-verification/email-verification-prompt.notifications.notification_resend_throttled.title', [
34+
'seconds' => $exception->secondsUntilAvailable,
35+
'minutes' => ceil($exception->secondsUntilAvailable / 60),
36+
]))
37+
->body(array_key_exists('body', __('filament-panels::pages/auth/email-verification/email-verification-prompt.notifications.notification_resend_throttled') ?: []) ? __('filament-panels::pages/auth/email-verification/email-verification-prompt.notifications.notification_resend_throttled.body', [
38+
'seconds' => $exception->secondsUntilAvailable,
39+
'minutes' => ceil($exception->secondsUntilAvailable / 60),
40+
]) : null)
41+
->danger()
42+
->send();
43+
44+
return;
45+
}
46+
47+
$user = Filament::auth()->user();
48+
49+
if (! method_exists($user, 'notify')) {
50+
$userClass = $user::class;
51+
52+
throw new Exception("Model [{$userClass}] does not have a [notify()] method.");
53+
}
54+
55+
$notification = new VerifyEmail();
56+
$notification->url = Filament::getVerifyEmailUrl($user);
57+
58+
$settings->loadMailSettingsToConfig();
59+
60+
$user->notify($notification);
61+
62+
Notification::make()
63+
->title(__('filament-panels::pages/auth/email-verification/email-verification-prompt.notifications.notification_resent.title'))
64+
->success()
65+
->send();
66+
});
67+
}
68+
69+
public function getTitle(): string | Htmlable
70+
{
71+
return __('filament-panels::pages/auth/email-verification/email-verification-prompt.title');
72+
}
73+
74+
public function getHeading(): string | Htmlable
75+
{
76+
return __('filament-panels::pages/auth/email-verification/email-verification-prompt.heading');
77+
}
78+
}

app/Filament/Pages/Setting/ManageMail.php

+10-22
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ protected function fillForm(): void
3838
{
3939
$this->callHook('beforeFill');
4040

41-
$settings = app(static::getSettings());
42-
43-
$data = $this->mutateFormDataBeforeFill($settings->toArray());
41+
$data = $this->mutateFormDataBeforeFill(app(static::getSettings())->toArray());
4442

4543
$this->form->fill($data);
4644

@@ -108,7 +106,8 @@ public function form(Form $form): Form
108106
Forms\Components\TextInput::make('mail_to')
109107
->label(fn () => __('page.mail_settings.fields.mail_to'))
110108
->hiddenLabel()
111-
->placeholder(fn () => __('page.mail_settings.fields.placeholder.receiver_email')),
109+
->placeholder(fn () => __('page.mail_settings.fields.placeholder.receiver_email'))
110+
->required(),
112111
Forms\Components\Actions::make([
113112
Forms\Components\Actions\Action::make('Send Test Mail')
114113
->label(fn () => __('page.mail_settings.actions.send_test_mail'))
@@ -126,7 +125,7 @@ public function form(Form $form): Form
126125
->statePath('data');
127126
}
128127

129-
public function save(): void
128+
public function save(MailSettings $settings = null): void
130129
{
131130
try {
132131
$this->callHook('beforeValidate');
@@ -139,8 +138,6 @@ public function save(): void
139138

140139
$this->callHook('beforeSave');
141140

142-
$settings = app(static::getSettings());
143-
144141
$settings->fill($data);
145142
$settings->save();
146143

@@ -150,27 +147,18 @@ public function save(): void
150147

151148
$this->redirect(static::getUrl(), navigate: FilamentView::hasSpaMode() && is_app_url(static::getUrl()));
152149
} catch (\Throwable $th) {
153-
throw $th;
154150
$this->sendErrorNotification('Failed to update settings. '.$th->getMessage());
151+
throw $th;
155152
}
156153
}
157154

158-
public function sendTestMail()
155+
public function sendTestMail(MailSettings $settings = null)
159156
{
160-
$settings = $this->form->getState();
161-
162-
config([
163-
'mail.mailers.smtp.host' => $settings['host'],
164-
'mail.mailers.smtp.port' => $settings['port'],
165-
'mail.mailers.smtp.encryption' => $settings['encryption'],
166-
'mail.mailers.smtp.username' => $settings['username'],
167-
'mail.mailers.smtp.password' => $settings['password'],
168-
'mail.from.address' => $settings['from_address'],
169-
'mail.from.name' => $settings['from_name'],
170-
]);
157+
$data = $this->form->getState();
171158

159+
$settings->loadMailSettingsToConfig($data);
172160
try {
173-
$mailTo = $settings['mail_to'];
161+
$mailTo = $data['mail_to'];
174162
$mailData = [
175163
'title' => 'This is a test email to verify SMTP settings',
176164
'body' => 'This is for testing email using smtp.'
@@ -196,7 +184,7 @@ public function sendErrorNotification($title)
196184
{
197185
Notification::make()
198186
->title($title)
199-
->error()
187+
->danger()
200188
->send();
201189
}
202190

app/Filament/Resources/UserResource.php

+38-8
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@
33
namespace App\Filament\Resources;
44

55
use App\Filament\Resources\UserResource\Pages;
6-
use App\Filament\Resources\UserResource\RelationManagers;
76
use App\Models\User;
7+
use App\Settings\MailSettings;
8+
use Exception;
9+
use Filament\Facades\Filament;
810
use Filament\Forms;
11+
use Filament\Forms\Components\Actions\Action;
912
use Filament\Forms\Components\Select;
1013
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
1114
use Filament\Forms\Form;
12-
use Filament\Forms\Get;
15+
use Filament\Notifications\Auth\VerifyEmail;
16+
use Filament\Notifications\Notification;
1317
use Filament\Resources\Resource;
1418
use Filament\Tables;
1519
use Filament\Tables\Columns\SpatieMediaLibraryImageColumn;
1620
use Filament\Tables\Table;
1721
use Illuminate\Contracts\Support\Htmlable;
18-
use Illuminate\Database\Eloquent\Builder;
1922
use Illuminate\Database\Eloquent\Model;
20-
use Illuminate\Database\Eloquent\SoftDeletingScope;
21-
use Illuminate\Support\Facades\DB;
2223
use Illuminate\Support\Facades\Hash;
2324
use Illuminate\Support\Str;
2425

@@ -35,7 +36,6 @@ public static function form(Form $form): Form
3536
{
3637
return $form
3738
->schema([
38-
3939
Forms\Components\Section::make()
4040
->schema([
4141
Forms\Components\Grid::make()
@@ -97,12 +97,21 @@ public static function form(Form $form): Form
9797
Forms\Components\Section::make()
9898
->schema([
9999
Forms\Components\Placeholder::make('email_verified_at')
100+
->label(__('resource.general.email_verified_at'))
100101
->content(fn (User $record): ?string => $record->email_verified_at),
102+
Forms\Components\Actions::make([
103+
Action::make('resend_verification')
104+
->label(__('resource.user.actions.resend_verification'))
105+
->color('secondary')
106+
->action(fn (MailSettings $settings, Model $record) => static::doResendEmailVerification($settings, $record)),
107+
])
108+
->hidden(fn (User $user) => $user->email_verified_at != null)
109+
->fullWidth(),
101110
Forms\Components\Placeholder::make('created_at')
102-
->label('Created at')
111+
->label(__('resource.general.created_at'))
103112
->content(fn (User $record): ?string => $record->created_at?->diffForHumans()),
104113
Forms\Components\Placeholder::make('updated_at')
105-
->label('Last modified at')
114+
->label(__('resource.general.updated_at'))
106115
->content(fn (User $record): ?string => $record->updated_at?->diffForHumans()),
107116
])
108117
->hidden(fn (string $operation): bool => $operation === 'create'),
@@ -191,4 +200,25 @@ public static function getNavigationGroup(): ?string
191200
{
192201
return __("menu.nav_group.access");
193202
}
203+
204+
public static function doResendEmailVerification($settings = null, $user): void
205+
{
206+
if (! method_exists($user, 'notify')) {
207+
$userClass = $user::class;
208+
209+
throw new Exception("Model [{$userClass}] does not have a [notify()] method.");
210+
}
211+
212+
$notification = new VerifyEmail();
213+
$notification->url = Filament::getVerifyEmailUrl($user);
214+
215+
$settings->loadMailSettingsToConfig();
216+
217+
$user->notify($notification);
218+
219+
Notification::make()
220+
->title(__('resource.user.notifications.notification_resent.title'))
221+
->success()
222+
->send();
223+
}
194224
}

app/Filament/Resources/UserResource/Pages/CreateUser.php

+29-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
namespace App\Filament\Resources\UserResource\Pages;
44

55
use App\Filament\Resources\UserResource;
6-
use Filament\Actions;
6+
use App\Settings\MailSettings;
7+
use Exception;
8+
use Filament\Facades\Filament;
9+
use Filament\Notifications\Auth\VerifyEmail;
10+
use Filament\Notifications\Notification;
711
use Filament\Resources\Pages\CreateRecord;
812

913
class CreateUser extends CreateRecord
@@ -14,4 +18,28 @@ protected function getRedirectUrl(): string
1418
{
1519
return $this->getResource()::getUrl('index');
1620
}
21+
22+
protected function afterCreate(): void
23+
{
24+
$user = $this->record;
25+
$settings = app(MailSettings::class);
26+
27+
if (! method_exists($user, 'notify')) {
28+
$userClass = $user::class;
29+
30+
throw new Exception("Model [{$userClass}] does not have a [notify()] method.");
31+
}
32+
33+
$notification = new VerifyEmail();
34+
$notification->url = Filament::getVerifyEmailUrl($user);
35+
36+
$settings->loadMailSettingsToConfig();
37+
38+
$user->notify($notification);
39+
40+
Notification::make()
41+
->title(__('resource.user.notifications.notification_resent.title'))
42+
->success()
43+
->send();
44+
}
1745
}

app/Models/User.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
namespace App\Models;
44

5-
// use Illuminate\Contracts\Auth\MustVerifyEmail;
65
use Filament\Models\Contracts\FilamentUser;
76
use Filament\Models\Contracts\HasAvatar;
87
use Filament\Models\Contracts\HasName;
98
use Filament\Panel;
9+
use Illuminate\Contracts\Auth\MustVerifyEmail;
1010
use Illuminate\Database\Eloquent\Concerns\HasUuids;
1111
use Illuminate\Database\Eloquent\Factories\HasFactory;
1212
use Illuminate\Foundation\Auth\User as Authenticatable;
@@ -18,7 +18,7 @@
1818
use Spatie\MediaLibrary\MediaCollections\Models\Media;
1919
use Spatie\Permission\Traits\HasRoles;
2020

21-
class User extends Authenticatable implements FilamentUser, HasAvatar, HasName, HasMedia
21+
class User extends Authenticatable implements FilamentUser, MustVerifyEmail, HasAvatar, HasName, HasMedia
2222
{
2323
use InteractsWithMedia;
2424
use HasUuids, HasRoles;

app/Providers/Filament/AdminPanelProvider.php

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Providers\Filament;
44

5+
use App\Filament\Pages\Auth\EmailVerification;
56
use App\Filament\Pages\Auth\Login;
67
use App\Livewire\MyProfileExtended;
78
use App\Settings\GeneralSettings;
@@ -30,6 +31,7 @@ public function panel(Panel $panel): Panel
3031
->id('admin')
3132
->path('admin')
3233
->login(Login::class)
34+
->emailVerification(EmailVerification::class)
3335
->favicon(fn (GeneralSettings $settings) => Storage::url($settings->site_favicon))
3436
->brandName(fn (GeneralSettings $settings) => $settings->brand_name)
3537
->brandLogo(fn (GeneralSettings $settings) => Storage::url($settings->brand_logo))

app/Settings/MailSettings.php

+13
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,17 @@ public static function encrypted(): array
2929
'password',
3030
];
3131
}
32+
33+
public function loadMailSettingsToConfig($data = null): void
34+
{
35+
config([
36+
'mail.mailers.smtp.host' => $data['host'] ?? $this->host,
37+
'mail.mailers.smtp.port' => $data['port'] ?? $this->port,
38+
'mail.mailers.smtp.encryption' => $data['encryption'] ?? $this->encryption,
39+
'mail.mailers.smtp.username' => $data['username'] ?? $this->username,
40+
'mail.mailers.smtp.password' => $data['password'] ?? $this->password,
41+
'mail.from.address' => $data['from_address'] ?? $this->from_address,
42+
'mail.from.name' => $data['from_name'] ?? $this->from_name,
43+
]);
44+
}
3245
}

0 commit comments

Comments
 (0)