Skip to content

Commit d9bcbec

Browse files
authored
Intranet preset (#40)
* Add unedited files * Add pages, roles * Improve all partials, fieldsets and the config * Fix excluder imports * Add model * Add mail vendor template * User proper model * Update order * Fixes * Refactor form input partial * Remove sanctum * Add lock down page toggle
1 parent 2692228 commit d9bcbec

31 files changed

+1311
-1
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
node_modules
2-
vendor
2+
/vendor
33
mix-manifest.json
44
composer.lock
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App\Listeners;
4+
5+
use Statamic\Events\UserRegistered;
6+
7+
class SendEmailVerificationNotification
8+
{
9+
/**
10+
* Create the event listener.
11+
*
12+
* @return void
13+
*/
14+
public function __construct()
15+
{
16+
//
17+
}
18+
19+
/**
20+
* Handle the event.
21+
*
22+
* @param object $event
23+
*/
24+
public function handle(UserRegistered $event): void
25+
{
26+
$event->user->sendEmailVerificationNotification();
27+
}
28+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace App\Listeners;
4+
5+
use Statamic\Events\UserCreated;
6+
use Statamic\Statamic;
7+
8+
class SetUserEmailVerified
9+
{
10+
/**
11+
* Create the event listener.
12+
*
13+
* @return void
14+
*/
15+
public function __construct()
16+
{
17+
//
18+
}
19+
20+
/**
21+
* Handle the event.
22+
*
23+
* @param \App\Events\UserRegistered $event
24+
*/
25+
public function handle(UserCreated $event): void
26+
{
27+
$user = $event->user;
28+
if (Statamic::isCpRoute() && ! $user->email_verified_at) {
29+
$user->set('email_verified_at', now())->save();
30+
}
31+
}
32+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use Illuminate\Auth\MustVerifyEmail as MustVerifyEmailTrait;
6+
use Illuminate\Contracts\Auth\MustVerifyEmail;
7+
8+
class CustomUser extends \Statamic\Auth\File\User implements MustVerifyEmail
9+
{
10+
use MustVerifyEmailTrait;
11+
12+
public function markEmailAsVerified()
13+
{
14+
$this->email_verified_at = now();
15+
16+
return $this->save();
17+
}
18+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace App\Statamic;
4+
5+
use Statamic\Contracts\Entries\Entry;
6+
use Statamic\Facades\Data;
7+
use Statamic\StaticCaching\DefaultUrlExcluder;
8+
9+
class CustomUrlExcluder extends DefaultUrlExcluder
10+
{
11+
public function isExcluded(string $url): bool
12+
{
13+
if (parent::isExcluded($url)) {
14+
return true;
15+
}
16+
17+
$entry = Data::findByRequestUrl($url);
18+
19+
if (! $entry instanceof Entry) {
20+
return false;
21+
}
22+
23+
return preg_match_all('/"exclude_from_static_caching":(true|"true")/', $entry->values()->toJson());
24+
}
25+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use Statamic\Http\Controllers\UserController as StatamicUserController;
6+
7+
class UserController extends StatamicUserController
8+
{
9+
public function __construct()
10+
{
11+
$this->middleware('throttle:6,1')->only('register');
12+
}
13+
}
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
<?php
2+
3+
return [
4+
'handle' => 'intranet',
5+
'name' => 'Intranet',
6+
'description' => 'Intranet with frontend users and email verification.',
7+
'operations' => [
8+
[
9+
'type' => 'copy',
10+
'input' => 'app/http/Controllers/UserController.php',
11+
'output' => 'app/http/Controllers/UserController.php',
12+
],
13+
[
14+
'type' => 'copy',
15+
'input' => 'app/Listeners/SendEmailVerificationNotification.php',
16+
'output' => 'app/Listeners/SendEmailVerificationNotification.php',
17+
],
18+
[
19+
'type' => 'copy',
20+
'input' => 'app/models/CustomUser.php',
21+
'output' => 'app/models/CustomUser.php',
22+
],
23+
[
24+
'type' => 'copy',
25+
'input' => 'app/Listeners/SetUserEmailVerified.php',
26+
'output' => 'app/Listeners/SetUserEmailVerified.php',
27+
],
28+
[
29+
'type' => 'copy',
30+
'input' => 'app/Statamic/CustomUrlExcluder.php',
31+
'output' => 'app/Statamic/CustomUrlExcluder.php',
32+
],
33+
[
34+
'type' => 'copy',
35+
'input' => 'resources/blueprints/user.yaml',
36+
'output' => 'resources/blueprints/user.yaml',
37+
],
38+
[
39+
'type' => 'copy',
40+
'input' => 'resources/blueprints/globals/intranet.yaml',
41+
'output' => 'resources/blueprints/globals/intranet.yaml',
42+
],
43+
[
44+
'type' => 'copy',
45+
'input' => 'content/globals/intranet.yaml',
46+
'output' => 'content/globals/intranet.yaml',
47+
],
48+
[
49+
'type' => 'copy',
50+
'input' => 'resources/fieldsets/account.yaml',
51+
'output' => 'resources/fieldsets/account.yaml',
52+
],
53+
[
54+
'type' => 'copy',
55+
'input' => 'resources/fieldsets/email_verification.yaml',
56+
'output' => 'resources/fieldsets/email_verification.yaml',
57+
],
58+
[
59+
'type' => 'copy',
60+
'input' => 'resources/fieldsets/login.yaml',
61+
'output' => 'resources/fieldsets/login.yaml',
62+
],
63+
[
64+
'type' => 'copy',
65+
'input' => 'resources/fieldsets/password_forgotten.yaml',
66+
'output' => 'resources/fieldsets/password_forgotten.yaml',
67+
],
68+
[
69+
'type' => 'copy',
70+
'input' => 'resources/fieldsets/password_reset.yaml',
71+
'output' => 'resources/fieldsets/password_reset.yaml',
72+
],
73+
[
74+
'type' => 'copy',
75+
'input' => 'resources/fieldsets/register.yaml',
76+
'output' => 'resources/fieldsets/register.yaml',
77+
],
78+
[
79+
'type' => 'copy',
80+
'input' => 'resources/views/components/_form_input.antlers.html',
81+
'output' => 'resources/views/components/_form_input.antlers.html',
82+
],
83+
[
84+
'type' => 'copy',
85+
'input' => 'resources/views/components/_login.antlers.html',
86+
'output' => 'resources/views/components/_login.antlers.html',
87+
],
88+
[
89+
'type' => 'copy',
90+
'input' => 'resources/views/page_builder/_account.antlers.html',
91+
'output' => 'resources/views/page_builder/_account.antlers.html',
92+
],
93+
[
94+
'type' => 'copy',
95+
'input' => 'resources/views/page_builder/_email_verification.antlers.html',
96+
'output' => 'resources/views/page_builder/_email_verification.antlers.html',
97+
],
98+
[
99+
'type' => 'copy',
100+
'input' => 'resources/views/page_builder/_login.antlers.html',
101+
'output' => 'resources/views/page_builder/_login.antlers.html',
102+
],
103+
[
104+
'type' => 'copy',
105+
'input' => 'resources/views/page_builder/_password_forgotten.antlers.html',
106+
'output' => 'resources/views/page_builder/_password_forgotten.antlers.html',
107+
],
108+
[
109+
'type' => 'copy',
110+
'input' => 'resources/views/page_builder/_password_reset.antlers.html',
111+
'output' => 'resources/views/page_builder/_password_reset.antlers.html',
112+
],
113+
[
114+
'type' => 'copy',
115+
'input' => 'resources/views/page_builder/_register.antlers.html',
116+
'output' => 'resources/views/page_builder/_register.antlers.html',
117+
],
118+
[
119+
'type' => 'copy',
120+
'input' => 'resources/views/vendor/mail/html/message.blade.php',
121+
'output' => 'resources/views/vendor/mail/html/message.blade.php',
122+
],
123+
[
124+
'type' => 'copy',
125+
'input' => 'content/collections/pages/account.md',
126+
'output' => 'content/collections/pages/account.md',
127+
],
128+
[
129+
'type' => 'copy',
130+
'input' => 'content/collections/pages/email-verification.md',
131+
'output' => 'content/collections/pages/email-verification.md',
132+
],
133+
[
134+
'type' => 'copy',
135+
'input' => 'content/collections/pages/login.md',
136+
'output' => 'content/collections/pages/login.md',
137+
],
138+
[
139+
'type' => 'copy',
140+
'input' => 'content/collections/pages/password-forgotten.md',
141+
'output' => 'content/collections/pages/password-forgotten.md',
142+
],
143+
[
144+
'type' => 'copy',
145+
'input' => 'content/collections/pages/password-reset.md',
146+
'output' => 'content/collections/pages/password-reset.md',
147+
],
148+
[
149+
'type' => 'copy',
150+
'input' => 'content/collections/pages/register.md',
151+
'output' => 'content/collections/pages/register.md',
152+
],
153+
[
154+
'type' => 'notify',
155+
'content' => "To install the following page builder blocks, optionally create a new group named `Account` when prompted. Use the description `Account based frontend user blocks.`. and set the icon to `user-multiple`.",
156+
],
157+
[
158+
'type' => 'update_page_builder',
159+
'block' => [
160+
'name' => 'Account',
161+
'instructions' => 'Edit account detailis',
162+
'icon' => 'user-avatar',
163+
'handle' => 'account',
164+
],
165+
],
166+
[
167+
'type' => 'update_page_builder',
168+
'block' => [
169+
'name' => 'Email verification',
170+
'instructions' => 'Email verification page.',
171+
'icon' => 'social-mail-send-email-message',
172+
'handle' => 'email_verification',
173+
],
174+
],
175+
[
176+
'type' => 'update_page_builder',
177+
'block' => [
178+
'name' => 'Login',
179+
'instructions' => 'The login form.',
180+
'icon' => 'user-security-lock',
181+
'handle' => 'login',
182+
],
183+
],
184+
[
185+
'type' => 'update_page_builder',
186+
'block' => [
187+
'name' => 'Password forgotten',
188+
'instructions' => 'The password forgotten form.',
189+
'icon' => 'security-lock',
190+
'handle' => 'password_forgotten',
191+
],
192+
],
193+
[
194+
'type' => 'update_page_builder',
195+
'block' => [
196+
'name' => 'Password reset',
197+
'instructions' => 'The password reset form.',
198+
'icon' => 'security-unlock',
199+
'handle' => 'password_reset',
200+
],
201+
],
202+
[
203+
'type' => 'update_page_builder',
204+
'block' => [
205+
'name' => 'Register',
206+
'instructions' => 'The register form.',
207+
'icon' => 'login-key-2',
208+
'handle' => 'register',
209+
],
210+
],
211+
[
212+
'type' => 'update_role',
213+
'role' => 'editor',
214+
'permissions' => ['edit intranet globals'],
215+
],
216+
[
217+
'type' => 'notify',
218+
'content' => "Add this to the `boot()` method in your `AppServiceProvider.php`.:\n\n\$this->app->bind(\Statamic\Http\Controllers\UserController::class, \App\Http\Controllers\UserController::class);",
219+
],
220+
[
221+
'type' => 'notify',
222+
'content' => "Add this to the `boot()` method in your `AppServiceProvider.php`.:\n\n\$this->app->bind(\Statamic\Contracts\Auth\User::class, \App\Models\CustomUser::class);",
223+
],
224+
[
225+
'type' => 'notify',
226+
'content' => "Add this to the `register()` method in your `AppServiceProvider.php`.:\n\n\$this->app->bind(\App\Statamic\CustomUrlExcluder::class, function (\$app) {\n\treturn new \App\Statamic\CustomUrlExcluder (\n\t\t\$app[\Statamic\StaticCaching\Cacher::class]->getBaseUrl(),\n\t\t\$app['config']['statamic.static_caching.exclude.urls'] ?? []\n\t);\n});",
227+
],
228+
[
229+
'type' => 'notify',
230+
'content' => "Add this to your exclude array in `config/statamic/static_caching.php`:\n\n'class' => \App\Statamic\CustomUrlExcluder::class,",
231+
],
232+
[
233+
'type' => 'notify',
234+
'content' => "Add this as your `registration_form_honeypot_field` value in `config/statamic/users.php`:\n\n'registration_form_honeypot_field' => 'fax',",
235+
],
236+
[
237+
'type' => 'notify',
238+
'content' => "Add this to your navigation or where an account/login button makes sense:\n\n{{ partial:components/login }}",
239+
],
240+
[
241+
'type' => 'notify',
242+
'content' => "Add the following to your routes file in `web.php`:\n\nuse Statamic\Facades\User;\nuse Illuminate\Auth\Events\Verified;\nuse Illuminate\Http\Request;\nuse Illuminate\Support\Facades\Auth;\nuse Illuminate\Support\Facades\Route;\nuse Statamic\Facades\Entry;\nuse Statamic\Globals\GlobalSet;\nuse Statamic\Http\Middleware\Localize;\n\n// This is the URL that the email verifcation link points to.\nRoute::get('/email-verification/{id}/{hash}', function (Request \$request) {\n\t\$user = User::find(\$request->route('id'));\n\n\tif (! hash_equals((string) \$user->getKey(), (string) \$request->route('id'))) {\n\t\tabort(403);\n\t}\n\n\tif (! hash_equals(sha1(\$user->getEmailForVerification()), (string) \$request->route('hash'))) {\n\t\tabort(403);\n\t}\n\n\tAuth::login(\$user);\n\n\tif (! \$user->hasVerifiedEmail()) {\n\t\t\$user->markEmailAsVerified();\n\n\tevent(new Verified(\$user));\n\t}\n\n\t\$accountEntry = Entry::find(GlobalSet::findByHandle('intranet')\n\t\t->inDefaultSite()\n\t\t->get('account_entry'));\n\n\treturn redirect(\$accountEntry->url());\n\t})->middleware(['signed'])->name('verification.verify');\n\n// This route is used to resend the email verification link.\nRoute::post('/email-verification/notificatie', function (Request \$request) {\n\t\$request->user()->sendEmailVerificationNotification();\n\n\treturn back()->with('success', 'Verification link sent.');\n})->middleware(['auth', 'throttle:6,1', Localize::class])->name('verification.send');",
243+
],
244+
[
245+
'type' => 'notify',
246+
'content' => "Add this to the blueprints where you want to be able to require users to login:\n\n-\n\tdisplay: Intranet\n\tfields:\n\t\t-\n\t\t\thandle: requires_login\n\t\t\tfield:\n\t\t\t\ttype: toggle\n\t\t\t\tdisplay: 'Requires login'\n\t\t\t\tinstructions_position: below",
247+
],
248+
[
249+
'type' => 'notify',
250+
'content' => "Add this to the templates where you want to be able to require users to login:\n\n{{ if requires_login }}\n\t{{ user }}\n\t\t{{ if !email_verified_at }}\n\t\t\t{{ redirect to=\"{ intranet:login_entry | url }?redirect={{ uri }}\" }}\n\t\t{{ /if }}\n\t{{ /user }}\n{{ /if }}",
251+
],
252+
[
253+
'type' => 'notify',
254+
'content' => "Add this to your `lang/locale/strings.php` file:\n(and possibly any other locales you support)\n\n'account' => 'Account',\n'account_cancel' => 'Cancel',\n'account_current_password' => 'Current password',\n'account_email' => 'Email',\n'account_first_name' => 'First name',\n'account_last_name' => 'Last name',\n'account_login' => 'Log in',\n'account_logout' => 'Log out',\n'account_new_password' => 'New password',\n'account_new_password_confirmation' => 'Confirm new password',\n'account_password' => 'Password',\n'account_password_confirmation' => 'Confirm password',\n'account_password_forgotten' => 'Forgot your password?',\n'account_password_reset' => 'Reset password',\n'account_password_reset_request' => 'Send email',\n'account_password_save' => 'Change password',\n'account_register' => 'Register',\n'account_reset_invalid' => 'This password reset url is invalid.',\n'account_save' => 'Save changes',\n'account_verification_resend' => 'Resend email',\n'account_verification_resend_succes' => 'The email has been resend.',",
255+
],
256+
],
257+
];

0 commit comments

Comments
 (0)